From 422f0eb14af171fe8c29e3ae31372f8e56c198dd Mon Sep 17 00:00:00 2001 From: defifuture <67232250+defifuture@users.noreply.github.com> Date: Fri, 25 Sep 2020 20:54:13 +0200 Subject: [PATCH 1/6] EIP: economic viability of batched meta transactions (initial commit) --- EIPS/eip-batched_meta_transactions.md | 641 ++++++++++++++++++ .../batched-meta-txs-gas-usage-1st-2nd.png | Bin 0 -> 31276 bytes ...a-txs-directly-to-token-smart-contract.png | Bin 0 -> 45866 bytes ...vs_M-to-M_vs_M-to-1_gas-cost-structure.png | Bin 0 -> 44630 bytes 4 files changed, 641 insertions(+) create mode 100644 EIPS/eip-batched_meta_transactions.md create mode 100644 assets/eip-batched_meta_transactions/batched-meta-txs-gas-usage-1st-2nd.png create mode 100644 assets/eip-batched_meta_transactions/meta-txs-directly-to-token-smart-contract.png create mode 100644 assets/eip-batched_meta_transactions/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png diff --git a/EIPS/eip-batched_meta_transactions.md b/EIPS/eip-batched_meta_transactions.md new file mode 100644 index 0000000000000..6c6ee75116063 --- /dev/null +++ b/EIPS/eip-batched_meta_transactions.md @@ -0,0 +1,641 @@ +--- +eip: +title: The economic viability of batched meta transactions +author: Matt (@defifuture) +discussions-to: https://ethereum-magicians.org/t/batched-meta-transactions-from-multiple-users-is-this-ready-for-an-eip-draft/4613 +status: Draft +type: Informational +category: ERC +created: 2020-09-25 +requires: 20 +--- + +## Simple Summary + +A meta transaction is a cryptographically signed message that a user sends to a relayer who then makes an on-chain transaction based on the meta transaction data. A relayer effectively pays gas fees in Ether, while an original sender can compensate the relayer in tokens. + +This article explores the **economic viability** of **batched** meta transactions in terms of gas usage. + +The **purpose** of the research is to find out whether batched meta transactions **spend less gas** (per meta tx) than a normal on-chain token transfer transaction. + +Note that this research uses an implementation in form of a function called `processMetaBatch()` which **extends the ERC-20 token** standard. No other functions or contracts are involved, nor is there any usage of zkRollups or other L2 solutions. + +## Abstract + +Gas usage of batched meta transactions is affected by **many factors** ranging from the batch size, to the amount of expensive SSTORE instructions where storage value is set to non-zero from zero. + +In this research, tests have been made for various scenarios in order to determine gas usage and figure out **which kinds** of batched meta transactions are the **most cost-effective**. + +The results have shown that batched meta transactions make the most sense in case the receiver has a prior non-zero token balance and the sender has a prior non-zero meta nonce value. + +The **M-to-M** batched meta transactions use case (many senders, many receivers) turned out as **not economically viable enough** in terms of gas savings. + +On the other hand, the **M-to-1** use case (many senders, 1 receiver) showed **promising gas cost reductions**, while also having good potential for real-world usage. + +## Contents + +- [Motivation](#motivation) +- [Specification of a proof-of-concept](#specification-of-a-proof-of-concept) +- [Rationale](#rationale) +- [Backwards Compatibility](#backwards-compatibility) +- [Implementation](#implementation) +- [Security Considerations](#security-considerations) +- [Test Cases](#test-cases) +- [Types of batched meta transactions](#types-of-batched-meta-transactions) +- [Gas usage tests](#gas-usage-tests) + - [Benchmark](#benchmark) + - [The first meta transaction](#the-first-meta-transaction) + - [The second meta transaction (and subsequent transactions)](#the-second-meta-transaction-and-subsequent-transactions) +- [The economics](#the-economics) + - [M-to-M example](#m-to-m-example) + - [M-to-1 example](#m-to-1-example) +- [Conclusion](#conclusion) + +## Motivation + +Meta transactions have proven useful as a solution for Ethereum accounts that don't have any ether, but hold ERC-20 tokens and would like to move them (gas-less transactions). + +With rising gas prices, meta transactions could also serve as a solution to avoid high gas fees, if batched together in one on-chain transaction. + +This article explores the implementation and economic viability of that idea. + +## Specification of a proof-of-concept + +The implementation of the proof-of-concept is pretty straightforward. A user sends a meta transaction to a relayer (through relayer's web app, for example). The relayer waits for multiple meta txs to arrive until the meta tx fees (at least) cover the cost of the on-chain gas fee. + +![](../assets/eip-batched_meta_transactions/meta-txs-directly-to-token-smart-contract.png) + +Technically, the implementation means **adding a couple of functions** to the existing **ERC-20** token standard: + +- `processMetaBatch()` +- `nonceOf()` (optional) + +You can see the proof-of-concept implementation in this file: [ERC20MetaBatch.sol](/contracts/ERC20MetaBatch.sol). This is an extended ERC-20 contract with added meta tx batch transfer capabilities (see function `processMetaBatch()`). + +### `processMetaBatch()` + +The `processMetaBatch()` function is responsible for receiving and processing a batch of meta transactions that change token balances. + +```solidity +function processMetaBatch(address[] memory senders, + address[] memory recipients, + uint256[] memory amounts, + uint256[] memory relayerFees, + uint256[] memory blocks, + uint8[] memory sigV, + bytes32[] memory sigR, + bytes32[] memory sigS) public returns (bool) { + + address sender; + uint256 newNonce; + uint256 relayerFeesSum = 0; + bytes32 msgHash; + uint256 i; + + // loop through all meta txs + for (i = 0; i < senders.length; i++) { + sender = senders[i]; + newNonce = _metaNonces[sender] + 1; + + if(sender == address(0) || recipients[i] == address(0)) { + continue; // sender or recipient is 0x0 address, skip this meta tx + } + + // the meta tx should be processed until (including) the specified block number, otherwise it is invalid + if(block.number > blocks[i]) { + continue; // if current block number is bigger than the requested number, skip this meta tx + } + + // check if meta tx sender's balance is big enough + if(_balances[sender] < (amounts[i] + relayerFees[i])) { + continue; // if sender's balance is less than the amount and the relayer fee, skip this meta tx + } + + // check if the signature is valid + msgHash = keccak256(abi.encode(sender, recipients[i], amounts[i], relayerFees[i], newNonce, blocks[i], address(this), msg.sender)); + if(sender != ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", msgHash)), sigV[i], sigR[i], sigS[i])) { + continue; // if sig is not valid, skip to the next meta tx + } + + // set a new nonce for the sender + _metaNonces[sender] = newNonce; + + // transfer tokens + _balances[sender] -= (amounts[i] + relayerFees[i]); + _balances[recipients[i]] += amounts[i]; + relayerFeesSum += relayerFees[i]; + } + + // give the relayer the sum of all relayer fees + _balances[msg.sender] += relayerFeesSum; + + return true; +} +``` + +As you can see, the `processMetaBatch()` function takes the following parameters: + +- an array of **sender addresses** (meta txs senders, not relayers) +- an array of **receiver addresses** +- an array of **amounts** +- an array of **relayer fees** (relayer is `msg.sender`) +- an array of **block numbers** (a due "date" for meta tx to be processed) +- Three arrays that represent parts of a **signature** (v, r, s) + +**Each item** in these arrays represents **data of one meta tx**. That's why the **correct order** in the arrays is very important. + +If a relayer gets the order wrong, the `processMetaBatch()` function would notice that (when validating a signature), because the hash of the meta tx values would not match the signed hash. A meta transaction with an invalid signature is **skipped**. + +### `nonceOf()` (optional) + +Nonces are needed due to the replay protection (see *Replay attacks* under *Security Considerations*). + +The function `nonceOf()` is optional because if the meta nonce mapping is set to public, the function is not needed: + +```solidity +mapping (address => uint256) public _metaNonces; +``` + +This is the approach that Uniswap uses in its [UniswapV2ERC20.sol](https://github.com/Uniswap/uniswap-v2-core/blob/4dd59067c76dea4a0e8e4bfdda41877a6b16dedc/contracts/UniswapV2ERC20.sol#L19) smart contract. + +A more **appropriate** approach, though, is to set the mapping to **private** and access the values via the `nonceOf()` function: + +```solidity +mapping (address => uint256) private _metaNonces; + +// ... + +function nonceOf(address account) public view returns (uint256) { + return _metaNonces[account]; +} +``` + +> The EIP-2612 (`permit()` function) also requires a nonce mapping. At this point, I'm not sure yet if this mapping should be **re-used** in case a smart contract implements both this idea and EIP-2612. +> +> At the first glance, it seems the nonce mapping could be re-used, but this should be thought through (and tested) for possible security implications. + +## Rationale + +The reason for this EIP is to research the economic viability of batched meta transactions. At first glance, batching (meta) transactions seem to offer significant gas reduction benefits. + +If batched meta transactions do provide meaningful gas savings, the concept could be used as one of the approaches in Ethereum scaling. + +## Backwards Compatibility + +The code implementation of batched meta transactions is backwards compatible with ERC-20 (it only extends it with one function). + +## Implementation + +Link to the implementation (along with security considerations explained in the README): [https://github.com/defifuture/erc20-batched-meta-transactions](https://github.com/defifuture/erc20-batched-meta-transactions) + +The `processMetaBatch()` function can be found in **contracts/ERC20MetaBatch.sol**. + +## Security Considerations + +Here is a list of potential security issues and how are they addressed in this implementation. + +### Forging a meta transaction + +The solution against a relayer forging a meta transaction is for a user to sign the meta transaction with their private key. + +The `processMetaBatch()` function then verifies the signature using `ecrecover()`. + +### Replay attacks + +The `processMetaBatch()` function is secure against two types of a replay attack: + +1. A nonce prevents a replay attack where a relayer would send the same meta tx more than once. +2. The current smart contract address (`address(this)`) is included in the meta tx data hash, which prevents a relayer from sending a meta tx to different token smart contracts (see the code below, under Signature validation). + +### Signature validation + +Signing a meta transaction and validating the signature is crucial for this whole scheme to work. + +The `processMetaBatch()` function validates a meta tx signature, and if it's **invalid**, the meta tx is **skipped** (but the whole on-chain transaction is **not reverted**). + +```solidity +bytes32 msgHash = keccak256(abi.encode(sender, recipients[i], amounts[i], relayerFees[i], newNonce, blocks[i], address(this), msg.sender)); + +if(senders[i] != ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", msgHash)), sigV[i], sigR[i], sigS[i])) { + continue; // if sig is not valid, skip to the next meta tx in the loop +} +``` + +Why not reverting the whole on-chain transaction? Because there could be only one problematic meta tx, and the others should not be dropped just because of one rotten apple. + +That said, it is expected of relayers to validate meta txs in advance before relaying them. That's why relayers are not entitled to a relayer fee for an invalid meta tx. + +### Malicious relayer forcing a user into over-spending + +A malicious relayer could delay sending some user's meta transaction until the user would decide to make the token transaction on-chain. + +After that, the relayer would relay the delayed meta tx which would mean that the user would have made two token transactions (over-spending). + +**Solution:** Each meta transaction should have an "expiry date". This is defined in a form of a block number by which the meta transaction must be relayed on-chain. + +```solidity +function processMetaBatch(... + uint256[] memory blocks, + ...) public returns (bool) { + + //... + + // loop through all meta txs + for (i = 0; i < senders.length; i++) { + + // the meta tx should be processed until (including) the specified block number, otherwise it is invalid + if(block.number > blocks[i]) { + continue; // if current block number is bigger than the requested number, skip this meta tx + } + + //... +``` + +### Front-running attack + +A malicious relayer could scout the Ethereum mempool to steal meta transactions and front-run the original relayer. + +**Solution:** The protection that `processMetaBatch()` function uses is that it requires the meta tx sender to add the relayer's Ethereum address as one of the values in the hash (which is then signed). + +When the `processMetaBatch()` function generates a hash it includes the `msg.sender` address in it: + +```solidity +bytes32 msgHash = keccak256(abi.encode(sender, recipients[i], amounts[i], relayerFees[i], newNonce, blocks[i], address(this), msg.sender)); + +if(senders[i] != ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", msgHash)), sigV[i], sigR[i], sigS[i])) { + continue; // if sig is not valid, skip to the next meta tx in the loop +} +``` + +If the meta tx was "stolen", the signature check would fail because the `msg.sender` address would not be the same as the intended relayer's address. + +### A malicious (or too impatient) user sending a meta tx with the same nonce through multiple relayers at once + +A user that is either malicious or just impatient could submit a meta tx with the same nonce (for the same token contract) to various relayers. Only one of them would get the relayer fee (the first one on-chain), while the others would get an invalid meta transaction. + +**Solution:** Relayers could **share a list of their pending meta txs** between each other (sort of an info mempool). + +The relayers don't have to fear that someone would steal their respective pending transactions, due to the front-running protection (see above). + +If relayers see meta transactions from a certain sender address that have the same nonce and are supposed to be relayed to the same token smart contract, they can decide that only the first registered meta tx goes through and others are dropped (or in case meta txs were registered at the same time, the remaining meta tx could be randomly picked). + +At a minimum, relayers need to share this meta tx data (in order to detect meta tx collision): + +- sender address +- token address +- nonce + +### Too big due block number + +The relayer could trick the meta tx sender into adding too big due block number - this means a block by which the meta tx must be processed. The block number could be far in the future, for example, 10 years in the future. This means that the relayer would have 10 years to submit the meta transaction. + +**One way** to solve this problem is by adding an upper bound constraint for a block number within the smart contract. For example, we could say that the specified due block number must not be bigger than 100'000 blocks from the current one (this is around 17 days in the future if we assume 15 seconds block time). + +```solidity +// the meta tx should be processed until (including) the specified block number, otherwise it is invalid +if(block.number > blocks[i] || blocks[i] > (block.number + 100000)) { + // If current block number is bigger than the requested due block number, skip this meta tx. + // Also skip if the due block number is too big (bigger than 100'000 blocks in the future). + continue; +} +``` + +This addition could open new security implications, that's why it is left out of this proof-of-concept. But anyone who wishes to implement it should know about this potential constraint, too. + +**The other way** is to keep the `processMetaBatch()` function as it is and rather check for the too big due block number **on the relayer level**. In this case, the user could be notified about the problem and could issue a new meta tx with another relayer that would have a much lower block parameter (and the same nonce). + +## Test Cases + +Link to tests: [https://github.com/defifuture/erc20-batched-meta-transactions/tree/master/test](https://github.com/defifuture/erc20-batched-meta-transactions/tree/master/test) + +## Types of batched meta transactions + +There are three main types of batched meta transactions: + +- 1-to-M: 1 sender, many recipients +- M-to-1: many senders, 1 recipient +- M-to-M: many senders, many recipients + +Right from the start, we can see that **1-to-M use case does not make sense** for this implementation, because if there's only one unique sender in the whole batch, there's no need to sign and then validate each meta tx separately (which costs additional gas). In this case, a token multisender such as [Disperse.app](http://disperse.app/) can be more useful (higher throughput) and less costly. + +The *Gas usage* section below will thus focus **only** on the **M-to-1** and **M-to-M** use cases. + +> There are two additional types of batched meta transactions: +> +> - A batch where sender and recipient are the same address +> - A batch that has only one unique sender and only one unique recipient (but both different from each other) +> +> Both of these examples are very impractical and are not useful in reality. But the gas usage tests for both were made anyway (Test #2 and #3, respectively) and can be found in the [calculateGasCosts.js](/test/calculateGasCosts.js) file in the test folder. + +## Gas usage tests + +Gas usage is heavily dependent on whether a meta transaction is **the first transaction** of a **sender** (where prior nonce value is zero) and whether the **receiver** held any **prior token balance**. + +The gas usage tests are thus separated into two groups: + +- **First-meta-transaction tests** (initially sender has a zero nonce, and a receiver has a zero token balance) +- **Second-meta-transaction tests** (sender has a non-zero nonce value, and a receiver has a non-zero token balance) + +All the tests were run with different batch sizes: + +- 1 meta tx in the batch +- 5 meta txs in the batch +- 10 meta txs in the batch +- 50 meta txs in the batch +- 100 meta txs in the batch + +### Benchmark + +A benchmark for the following tests is gas usage cost in case of a **normal on-chain token transfer transaction**. + +There are **two possible benchmarks** and they both depend on whether a recipient has a prior non-zero token balance, or not. + +In case a **recipient's token balance** (prior to the meta tx) is **zero**, the on-chain transaction cost is **51'000 gas**. + +But if a **recipient's token balance is bigger than zero**, the on-chain token transfer transaction would cost only **36'000 gas**. + +### The first meta transaction + +In this group of tests, a **sender's nonce** prior to the meta tx is **always 0**. + +#### M-to-1 (to a zero-balance receiver) + +The M-to-1 (many senders, 1 receiver with a zero token balance) gas usage test results are the following: + +- 1 meta tx in the batch: 88666/meta tx (total gas: 88666) +- 5 meta txs in the batch: 47673.6/meta tx (total gas: 238368) +- 10 meta txs in the batch: 42553/meta tx (total gas: 425530) +- 50 meta txs in the batch: 38485.5/meta tx (total gas: 1924275) +- 100 meta txs in the batch: 38025.83/meta tx (total gas: 3802583) + +A further test has been done to determine that having 4 meta txs in a batch costs 50232 gas/meta tx. + +This means that the **M-to-1 use case beats the benchmark** (51'000 gas) in case of 4 or more meta txs in a batch. + +> Note that using 51'000 gas as a benchmark in this example might not be entirely fair because only the first meta tx is made towards the receiver with a zero token balance. After that, the receiver's balance is non-zero. +> +> Hence, the next test is more appropriate. + +#### M-to-1 (to a non-zero balance receiver) + +The M-to-1 (many senders, 1 receiver with a non-zero token balance) gas usage test results are the following: + +- 1 meta tx in the batch: 73666/meta tx (total gas: 73666) +- 5 meta txs in the batch: 44671.2/meta tx (total gas: 223356) +- 10 meta txs in the batch: 41049.4/meta tx (total gas: 410494) +- 50 meta txs in the batch: 38182.62/meta tx (total gas: 1909131) +- 100 meta txs in the batch: 37875.83/meta tx (total gas: 3787583) + +The **benchmark**, in this case, is **36'000 gas**, because the receiver already has a prior non-zero token balance. **None** of the batch sizes goes below the benchmark. + +#### M-to-M (to a zero-balance receiver) + +The M-to-M (many senders, many receivers) gas usage test results are the following: + +- 1 meta tx in the batch: 88666/meta tx (total gas: 88666) +- 5 meta txs in the batch: 63031.2/meta tx (total gas: 315156) +- 10 meta txs in the batch: 59833/meta tx (total gas: 598330) +- 50 meta txs in the batch: 57298.86/meta tx (total gas: 2864943) +- 100 meta txs in the batch: 57032.51/meta tx (total gas: 5703251) + +As you can see, the M-to-M example gas cost (per meta tx) in this case **never falls below** the benchmark value of **51'000 gas**. + +#### M-to-M (to a non-zero balance receiver) + +In this example (as opposed to the previous one), the recipient has a prior non-zero token balance: + +- 1 meta tx in the batch: 73678/meta tx (total gas: 73678) +- 5 meta txs in the batch: 48038.4/meta tx (total gas: 240192) +- 10 meta txs in the batch: 44842.6/meta tx (total gas: 448426) +- 50 meta txs in the batch: 42310.62/meta tx (total gas: 2115531) +- 100 meta txs in the batch: 42032.75/meta tx (total gas: 4203275) + +In this case, the benchmark is **36'000 gas** because the recipient had a prior non-zero token balance. As you can see, the gas used in this use case **never beats** the benchmark. + +
+ +In this group of batched meta transaction tests, none of the use cases beats the benchmark. Even the first example, M-to-1 (to a zero-balance receiver), cannot be considered as successful, because the benchmark should really be 36'000 after the first meta tx is processed. + +The main issue is, of course, the fact that it is each sender's **first** meta transaction, which means that the sender's nonce has to go from 0 to 1. This SSTORE operation is very expensive and takes 20'000 gas. + +Updating a non-zero value (for example raising a nonce value from 1 to 2) is a much less expensive operation. It costs only 5'000 gas. + +Let's now see the results of **the second** meta tx gas tests. + +### The second meta transaction (and subsequent transactions) + +Note that in this group of tests, the **sender's nonce is a non-zero value** (more precisely: 1). This brings visible gas reductions. + +#### M-to-1 (to a non-zero balance receiver) + +- 1 meta tx in the batch: 58666/meta tx (total gas: 58666) +- 5 meta txs in the batch: 29671.2/meta tx (total gas: 148356) +- 10 meta txs in the batch: 26048.2/meta tx (total gas: 260482) +- 50 meta txs in the batch: 23183.1/meta tx (total gas: 1159155) +- 100 meta txs in the batch: 22876.07/meta tx (total gas: 2287607) + +An additional test showed that the **benchmark** (36'000) **is beaten** already at 3 meta transactions in a batch. + +#### M-to-M (to a zero-balance receiver) + +- 1 meta tx in the batch: 73666/meta tx (total gas: 73666) +- 5 meta txs in the batch: 48026.4/meta tx (total gas: 240132) +- 10 meta txs in the batch: 44829.4/meta tx (total gas: 448294) +- 50 meta txs in the batch: 42298.14/meta tx (total gas: 2114907) +- 100 meta txs in the batch: 42032.27/meta tx (total gas: 4203227) + +In this case, the benchmark is 51'000, because the receiver has a zero-value balance. This M-to-M example **beats the benchmark** starting from 4 meta txs in a batch. + +#### M-to-M (to a non-zero balance receiver) + +- 1 meta tx in the batch: 58666/meta tx (total gas: 58666) +- 5 meta txs in the batch: 33024/meta tx (total gas: 165120) +- 10 meta txs in the batch: 29830.6/meta tx (total gas: 298306) +- 50 meta txs in the batch: 27307.98/meta tx (total gas: 1365399) +- 100 meta txs in the batch: 27033.59/meta tx (total gas: 2703359) + +An additional test shows that 4 or more meta txs in a batch have a **lower** average gas than the benchmark (36'000). + +
+ +All of the examples beat their respective benchmarks for the second or subsequent sender's meta transactions. + +### Graph + +This graph represents how M-to-1 and M-to-M fare in the case of the first and the second sender's meta transactions. + +![](../assets/eip-batched_meta_transactions/batched-meta-txs-gas-usage-1st-2nd.png) + +Note that only transactions where the benchmark is 36'000 are included (meaning the recipient has a prior non-zero token balance). + +## The economics + +Let's consider the real-world economic viability of both use cases, M-to-M and M-to-1, by calculating gas cost in USD for each. + +First, we need to make a few **assumptions**: + +**A) The gas price is 500 Gwei** + +The purpose of batched meta transactions is to lower the tx cost for the end-user, which means batching comes useful in times of high gas prices. + +**B) Ether price is 350 USD** + +At the time of writing these words, the ETH price is 350 USD, so let's take this as the price for our transaction cost calculations. + +**C) All meta transactions are sent to receivers with non-zero token balances** + +This means the benchmark is always 36'000 gas. Having a constant benchmark will make calculations and cost comparisons easier. + +**D) A relayer sends the batch after it reaches the size of 50 meta txs** + +Let's say the token is very popular, so there are plenty of people who want to send a meta transaction and the relayer has no trouble getting 50 meta transactions into a single batch. + +**E) A relayer includes (in a batch) no more than 15 meta txs from first-time senders** + +Meta transactions coming from first-time senders are the most expensive (because these senders have a zero nonce value). + +Since meta txs from first-time senders do not go below the benchmark, the relayer subsidizes them by charging second-time senders more. + +**F) The relayer wants to earn a margin equivalent to 1000 gas per each meta transaction** + +Running a relayer is a business that needs to earn a margin (and make a profit) in order to make it viable. + +--- + +Following the above assumptions, the formula to calculate the gas cost in USD is: + +``` +gas cost in USD = 0.000000001 * 500 Gwei * 350 USD * gas amount +``` + +### M-to-M example + +As per our assumptions, there are **15 first-time senders**. The cost of each such meta tx is **42'310.62 gas/mtx**. This is obviously above the benchmark: + +``` +gas amount above benchmark = (42311 gas/mtx - 36000) * 15 = 94665 gas +``` + +The gas amount above the benchmark for all 15 first-time senders is **94'665 gas**. + +With the **second-time senders**, the story is just the opposite. Each of their meta transactions costs **27'307.98 gas/mtx**, which is well below the benchmark. + +``` +gas amount below benchmark = (36000 - 27308 gas/mtx) * 35 = 304220 gas +``` + +The gas savings for all the 35 second-time senders is **304'220 gas**. + +Since relayers are passing the gas cost overages (over the benchmark) of first-time senders to second-time senders, we need to make additional calculations in order to determine the final gas cost per meta tx for second-time senders. + +We need to subtract the gas cost overage of first-time senders from the gas savings of second-time senders. In addition, we also need to subtract the margin that the relayer expects from this batch (`50 * 1000 gas`): + +``` +final gas savings for second-time senders = 304220 - 94665 - 50000 = 159555 gas +``` + +Next, let's divide this number by the amount of second-time senders: + +``` +final gas savings per each second-time sender = 159555 / 35 = 4559 gas +``` + +Instead of saving around 8'700 gas per meta tx, each second-time sender will only save 4'559 gas (due to subsidizing first-time senders). + +The meta tx gas cost for second-time senders is now the following: + +``` +meta tx gas cost = 36000 - 4559 = 31441 gas +``` + +To sum up, let's take a look at how much each of the users would pay for a meta transaction (or earn in case of a relayer): + +- **First-time sender:** 6.30 USD/mtx (0 USD savings compared to benchmark) +- **Second-time sender:** 5.50 USD/mtx (0.80 USD/mtx savings compared to benchmark) +- **Relayer's margin:** 0.175 USD/mtx (8.75 USD for the whole batch) + +The second-time sender would pay **13% less in tx fees** by submitting a meta tx, compared to doing an on-chain token transfer transaction (benchmark). + +### M-to-1 example + +Again, there are 15 first-time senders, whose meta transactions cost **38182.62 gas/mtx** each. This is **slightly above** the benchmark: + +``` +gas amount above benchmark = (38183 gas/mtx - 36000) * 15 = 32745 gas +``` + +The gas amount above the benchmark for all 15 first-time senders is **32'745 gas**. + +With the second-time senders, the story is the opposite (gas savings instead of gas cost overage). Each meta tx of a second-time sender costs only **23'183.1 gas/mtx**: + +``` +gas amount below benchmark = (36000 - 23183 gas/mtx) * 35 = 448595 gas +``` + +Next, we need to subtract the cost overage of first-time senders and the margin of a relayer: + +``` +final gas savings for second-time senders = 448595 - 32745 - 50000 = 365850 gas +``` + +Now, let's divide this number by the amount of second-time senders: + +``` +final gas savings per each second-time sender = 365850 / 35 = 10453 gas +``` + +The meta tx gas cost for second-time senders is the following: + +``` +meta tx gas cost = 36000 - 10453 = 25547 gas +``` + +This is, of course, less than the original amount of 23'183.1 gas/mtx, but still significantly below the benchmark. + +To sum up, let's take a look at how much each of the users would pay for a meta transaction (or earn in case of a relayer): + +- **First-time sender:** 6.30 USD/mtx (0 USD savings compared to benchmark) +- **Second-time sender:** 4.47 USD/mtx (1.83 USD/mtx savings compared to benchmark) +- **Relayer's margin:** 0.175 USD/mtx (8.75 USD for the whole batch) + +The second-time sender would pay **30% less in tx fees** by submitting a meta tx, compared to doing an on-chain token transfer transaction (benchmark). + +### Graph: batch gas structure comparison + +![](../assets/eip-batched_meta_transactions/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png) + +## Conclusion + +The gas savings for **M-to-M** meta transactions (13%) are much lower compared to gas savings for **M-to-1** meta txs (30%). + +That said, these savings heavily rely on a **strategy** that each relayer employs. The strategy in these examples is one option, but a relayer could decide to take a different path, which means the potential gas savings could be a lot different. + +Still, the ratio between M-to-M and M-to-1 gas costs should remain more or less the same. **M-to-1** obviously **does a much better job** at keeping gas **costs lower** than M-to-M. + +Considering the examples above, it's hard to see the M-to-M batching approach as an economically viable option (but, again, a different relayer strategy may counter this conclusion). + +A **much more promising** use case is using **M-to-1** batched meta transactions. This could be quite handy in concert **with other L2 solutions** (like sidechains) where a user needs to deposit funds to a constant address. + +Another use case could be locking tokens for staking, or putting them in a yield farming vault (applicable only if the receiving address is the same for all users). + +To conclude - depending on the **relayer strategy** and the **use case**, batched meta transactions can bring the transaction costs down for transferring tokens. + +But these reductions are **not as significant** as one would hope. In some cases it's even cheaper to send a normal on-chain token transaction instead of a meta transaction. + +Nevertheless, the topic of meta transactions **should be explored further** in order to find **specialized use cases** where meta transactions can provide a **valuable** solution. + +## Sources + +1. Griffith, Austin Thomas (2018): [Ethereum Meta Transactions](https://medium.com/@austin_48503/ethereum-meta-transactions-90ccf0859e84), Medium, 10 August 2018. +2. Kharlamov, Artem (2018): [Disperse Protocol](https://github.com/banteg/disperse-research/blob/master/paper/disperse.pdf), GitHub, 27 November 2018. +3. Lundfall, Martin (2020): [EIP-2612: permit – 712-signed approvals](https://eips.ethereum.org/EIPS/eip-2612), Ethereum Improvement Proposals, no. 2612, April 2020. +4. Sandford, Ronan (2019): [ERC-1776 Native Meta Transactions](https://github.com/ethereum/EIPs/issues/1776), GitHub, 25 February 2019. +5. Weiss, Yoav, Dror Tirosh, Alex Forshtat (2018): [EIP-1613: Gas stations network](https://eips.ethereum.org/EIPS/eip-1613), Ethereum Improvement Proposals, no. 1613, November 2018. + +### Acknowledgements + +A huge thanks to Patrick McCorry (@stonecoldpat), Artem Kharlamov (@banteg), Matt (@lightclient), and Ronan Sandford (@wighawag) for providing valuable feedback. + +## Copyright + +Copyright and related rights are waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/assets/eip-batched_meta_transactions/batched-meta-txs-gas-usage-1st-2nd.png b/assets/eip-batched_meta_transactions/batched-meta-txs-gas-usage-1st-2nd.png new file mode 100644 index 0000000000000000000000000000000000000000..f252f36b617ff093b8ac649bb4b9a2a141a3bfcc GIT binary patch literal 31276 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 literal 0 HcmV?d00001 diff --git a/assets/eip-batched_meta_transactions/meta-txs-directly-to-token-smart-contract.png b/assets/eip-batched_meta_transactions/meta-txs-directly-to-token-smart-contract.png new file mode 100644 index 0000000000000000000000000000000000000000..2c792f1429aa58db8368b7cd80a77c8daab30408 GIT binary patch literal 45866 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≦qLAZjuU8>DD$2H*)Q33}jF(@275zk`n>@8y^Us8 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%0D7<#@7$gcAsYGo`44!of}G6NBJTTA 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 literal 0 HcmV?d00001 diff --git a/assets/eip-batched_meta_transactions/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png b/assets/eip-batched_meta_transactions/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png new file mode 100644 index 0000000000000000000000000000000000000000..1849b39b085e56c1a20dc168735d453c77d4272e GIT binary patch literal 44630 zcmeFZWmwc**EcMUgovmJN(j=@B{76Z#~|Gy4bt5r3IYO3=g?i!ImC%dcS$2irwk$e z>;cd7^t#^r`SKp`r}wx$4o7GHv)5jG?Y-)^)}A0m1xb7yQk-kouHj2dJyW`N4Rsm( z4Z+3)pQy6au7ZD19F-)WUMuc>0N$WzTBv9^X~@g*8`)a37#iEYFkx}Cwgca~c1_TY zAN<$a#L1A-&HAN{BflGj>hc@>;Qz>vS*a*5zv5&Cq0*37q!hDtFrnmT;bLK<62hUR zq!e^8Hsx1(Ch>bXcn6^}cXG1hXJvJDb!BnoWU+NHV`b;#<6~vxVCCRo2H#+IbhmLb zbYr%0q`o5ZH=SoDjz$g^c1{+yHk3%ZhA(WLogh?H$cg^>bH%5Vh3UUD**N}Q7FZxF z@(C+D3mfY{w82n8oc1`4(^fOTvH!s{_j8n2&=?3nT1!uaw!9W{9HStjx7zPW4l#gS0kM$e{oJbaR) z{xE)Q{o8oF8O$Aa$XS1qYz8Co^0B%_i+)q&8p`h%sag@WPFWF@KRyy^#=e>4NJ;tX z8Y=eH%N!xfYsYXd^e_L86L~e4Wb_Xe@Od~GtjIby+0NK zM1%JS)&CXEzry%`C7K^@nGdppOMT8fj!qGMi#aJi5y=9sGW%;ISw3gS4xJ1+Qf*;m zS(YRDS%W$AJxv#9wwj*|`~>&<#gsB6LTm1P&x+NH*lxPeBX^ra$x|&*o7$C^kQmCA zk6azfNz_gD+^TgrKUxl)-drzfV$t{d`Bu|+*84F206+0t>5IuK>xh&TR!MUAOd|^~ z)5z!NzoNLjSUPgWs3s|EOg#@aK0eQo=-^vUqBcu*R@+(2-PU(syc4-pw_Y5QP{lzf zrIJX?IIA()$+Y-u&Y!@zBZ9_ZIoUP1Z#krrG*j}LpA6MpEet^*e5y$9duo5QR#0NR zK3b%ts7P7wx*ZeEq#lgvbn&ZA*tj(SKRVNWusQ*;+()4OD?Odc5%m_2XxyEySk~Bq z49TvEN~_k)ceC@)qJ(|29AlNK);@Ie^!GKw3fDR`+_S%g5O;xTD2a8Qp1bpua7{kS zmnVw0EyQ1lb}+BqM^}d4u0RA`2L~LRZY~do2p2xrI6rKgwH$mp~|Ehx7fPMenGnc+B?h`tB>3(r`xcHd}8U@zh zrbRYL{Yr%9=8jxnt&iUtv6_oZ)s#aQv%_jutjxmKP#QWqNz2hfhRw-p-dI%Vlke!` z^{ypH-;2;UBV$yDs|Fc#`ZlX)eXJDfNO@kabR1`S9^K(iUf)@a)$cS4htL+N6-5|@ z@n!3@y(2d|PTnohKg-vdEGI+_y46o4(KO3iZrUR=%+gMbfsXsfITm*-=L^=ar$j?*jdAK!LWvx9X zpViV7mOLsuKjEKa)Kp2Vj~LMNUe44n;}25|{Jyg23Q6lP9krgQu&3oTIr$L@?Jfw* z7>T^GsXEGpPR8$qorzEGs5jsN|M~U)lH}Z|wk@+VExynBeu=MiEQ{`sPNotr;d`8B zy;1InrH-YZM0t{t605Od_9Jeq(QciQ{y9OnsoDec{B?_*WYYt}T(_wBAR@X12aB>i z<(z~j;j>j}I((adwV#gcR;Atdr{k4Yv3zNOLh{PDLk-WId0n3g$||0I*>jJlGbQ@M zjw3Hu2eYz6jgBORtvpg>B5CD2UuL&1I=yUMDiAZnGE||3MBz+?M^E1&B);Kw$7-C2IYCZ07 zZuR1P`=Xow?CEGE3cg#4=N6wP+{2kN4<@yu_~2}Q)Ic9ig}ESR6P!C9-bTz@fpK|K z@I6|sVrLJs@TV$Y>v0bmS`}$kI#i1)=Ii?$ zeRbi#F%2qY(K~{=V-y zf&xKiKiBN%Fnzi;+O2sI+#SeN?vt{*9R^EU{b}NRVIDa2t<YHT*o=@$w#%-E8?p%(8*GO4scf(|dmB8sAP%mJ)5{$P*OX z2CPbafz8TtULVbVPb%oMHy}w1l`rUOmA{jxj#%nh+-W7?rF*Qd>m1DxxFrd-sW7Y8 zgL@37i{m2v(;;v8)ik^EN{*>B=tLsvpgg>6UmW&D(Wv1s3r_5+@-TBfDqAh?70>i8 zPGq-{dlt$iaCPWFR;Owm4Js1~mY++KnFNTf+QrK!@^lDnHy9PCnnO=sp`f9zPIrGU zKdortaLj78zK^c&>@cL)%jIDrPX{UX jA=t7tEc&zWxK|@PFyp08~OPeL0P&@c> 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 vAy8B2;Qw4LZ-fFY Date: Sat, 26 Sep 2020 00:49:08 +0200 Subject: [PATCH 2/6] #3005: link for discussions updated; eip number in the file name and assets folder set to 3005 --- ...eip-batched_meta_transactions.md => eip-3005.md} | 10 +++++----- .../batched-meta-txs-gas-usage-1st-2nd.png | Bin .../meta-txs-directly-to-token-smart-contract.png | Bin ...chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png | Bin 4 files changed, 5 insertions(+), 5 deletions(-) rename EIPS/{eip-batched_meta_transactions.md => eip-3005.md} (98%) rename assets/{eip-batched_meta_transactions => eip-3005}/batched-meta-txs-gas-usage-1st-2nd.png (100%) rename assets/{eip-batched_meta_transactions => eip-3005}/meta-txs-directly-to-token-smart-contract.png (100%) rename assets/{eip-batched_meta_transactions => eip-3005}/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png (100%) diff --git a/EIPS/eip-batched_meta_transactions.md b/EIPS/eip-3005.md similarity index 98% rename from EIPS/eip-batched_meta_transactions.md rename to EIPS/eip-3005.md index 6c6ee75116063..b8e2e6e231c4e 100644 --- a/EIPS/eip-batched_meta_transactions.md +++ b/EIPS/eip-3005.md @@ -1,8 +1,8 @@ --- -eip: +eip: 3005 title: The economic viability of batched meta transactions author: Matt (@defifuture) -discussions-to: https://ethereum-magicians.org/t/batched-meta-transactions-from-multiple-users-is-this-ready-for-an-eip-draft/4613 +discussions-to: https://ethereum-magicians.org/t/eip-3005-the-economic-viability-of-batched-meta-transactions/4673 status: Draft type: Informational category: ERC @@ -63,7 +63,7 @@ This article explores the implementation and economic viability of that idea. The implementation of the proof-of-concept is pretty straightforward. A user sends a meta transaction to a relayer (through relayer's web app, for example). The relayer waits for multiple meta txs to arrive until the meta tx fees (at least) cover the cost of the on-chain gas fee. -![](../assets/eip-batched_meta_transactions/meta-txs-directly-to-token-smart-contract.png) +![](../assets/eip-3005/meta-txs-directly-to-token-smart-contract.png) Technically, the implementation means **adding a couple of functions** to the existing **ERC-20** token standard: @@ -464,7 +464,7 @@ All of the examples beat their respective benchmarks for the second or subsequen This graph represents how M-to-1 and M-to-M fare in the case of the first and the second sender's meta transactions. -![](../assets/eip-batched_meta_transactions/batched-meta-txs-gas-usage-1st-2nd.png) +![](../assets/eip-3005/batched-meta-txs-gas-usage-1st-2nd.png) Note that only transactions where the benchmark is 36'000 are included (meaning the recipient has a prior non-zero token balance). @@ -602,7 +602,7 @@ The second-time sender would pay **30% less in tx fees** by submitting a meta tx ### Graph: batch gas structure comparison -![](../assets/eip-batched_meta_transactions/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png) +![](../assets/eip-3005/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png) ## Conclusion diff --git a/assets/eip-batched_meta_transactions/batched-meta-txs-gas-usage-1st-2nd.png b/assets/eip-3005/batched-meta-txs-gas-usage-1st-2nd.png similarity index 100% rename from assets/eip-batched_meta_transactions/batched-meta-txs-gas-usage-1st-2nd.png rename to assets/eip-3005/batched-meta-txs-gas-usage-1st-2nd.png diff --git a/assets/eip-batched_meta_transactions/meta-txs-directly-to-token-smart-contract.png b/assets/eip-3005/meta-txs-directly-to-token-smart-contract.png similarity index 100% rename from assets/eip-batched_meta_transactions/meta-txs-directly-to-token-smart-contract.png rename to assets/eip-3005/meta-txs-directly-to-token-smart-contract.png diff --git a/assets/eip-batched_meta_transactions/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png b/assets/eip-3005/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png similarity index 100% rename from assets/eip-batched_meta_transactions/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png rename to assets/eip-3005/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png From 7d443c72cc41c20948224a584534325323741281 Mon Sep 17 00:00:00 2001 From: defifuture <67232250+defifuture@users.noreply.github.com> Date: Sat, 26 Sep 2020 11:10:52 +0200 Subject: [PATCH 3/6] external links error fixed --- EIPS/eip-3005.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EIPS/eip-3005.md b/EIPS/eip-3005.md index b8e2e6e231c4e..d9df1e4ec11a3 100644 --- a/EIPS/eip-3005.md +++ b/EIPS/eip-3005.md @@ -70,7 +70,7 @@ Technically, the implementation means **adding a couple of functions** to the ex - `processMetaBatch()` - `nonceOf()` (optional) -You can see the proof-of-concept implementation in this file: [ERC20MetaBatch.sol](/contracts/ERC20MetaBatch.sol). This is an extended ERC-20 contract with added meta tx batch transfer capabilities (see function `processMetaBatch()`). +You can see the proof-of-concept implementation in this file: [ERC20MetaBatch.sol](https://github.com/defifuture/erc20-batched-meta-transactions/blob/master/contracts/ERC20MetaBatch.sol). This is an extended ERC-20 contract with added meta tx batch transfer capabilities (see function `processMetaBatch()`). ### `processMetaBatch()` @@ -325,7 +325,7 @@ The *Gas usage* section below will thus focus **only** on the **M-to-1** and **M > - A batch where sender and recipient are the same address > - A batch that has only one unique sender and only one unique recipient (but both different from each other) > -> Both of these examples are very impractical and are not useful in reality. But the gas usage tests for both were made anyway (Test #2 and #3, respectively) and can be found in the [calculateGasCosts.js](/test/calculateGasCosts.js) file in the test folder. +> Both of these examples are very impractical and are not useful in reality. But the gas usage tests for both were made anyway (Test 2 and 3, respectively) and can be found in the [calculateGasCosts.js](https://github.com/defifuture/erc20-batched-meta-transactions/blob/master/test/calculateGasCosts.js) file in the test folder. ## Gas usage tests From 12d3ca02b08d46bff3c48f9d132ead18ddc33b35 Mon Sep 17 00:00:00 2001 From: defifuture <67232250+defifuture@users.noreply.github.com> Date: Sun, 27 Sep 2020 19:21:06 +0200 Subject: [PATCH 4/6] EIP-3005 transformed from Informational EIP to Standards Track (ERC) EIP --- EIPS/eip-3005.md | 476 +++--------------- .../batched-meta-txs-gas-usage-1st-2nd.png | Bin 31276 -> 0 bytes ...vs_M-to-M_vs_M-to-1_gas-cost-structure.png | Bin 44630 -> 0 bytes 3 files changed, 69 insertions(+), 407 deletions(-) delete mode 100644 assets/eip-3005/batched-meta-txs-gas-usage-1st-2nd.png delete mode 100644 assets/eip-3005/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png diff --git a/EIPS/eip-3005.md b/EIPS/eip-3005.md index d9df1e4ec11a3..cb65e793a8c08 100644 --- a/EIPS/eip-3005.md +++ b/EIPS/eip-3005.md @@ -1,10 +1,10 @@ --- eip: 3005 -title: The economic viability of batched meta transactions +title: Batched meta transactions author: Matt (@defifuture) discussions-to: https://ethereum-magicians.org/t/eip-3005-the-economic-viability-of-batched-meta-transactions/4673 status: Draft -type: Informational +type: Standards Track category: ERC created: 2020-09-25 requires: 20 @@ -12,63 +12,38 @@ requires: 20 ## Simple Summary -A meta transaction is a cryptographically signed message that a user sends to a relayer who then makes an on-chain transaction based on the meta transaction data. A relayer effectively pays gas fees in Ether, while an original sender can compensate the relayer in tokens. +A meta transaction is a cryptographically signed message that a user sends to a relayer who then makes an on-chain transaction based on the meta transaction data. A relayer effectively pays gas fees in Ether, while a meta tx sender can compensate the relayer in tokens (a "gas-less" transaction). -This article explores the **economic viability** of **batched** meta transactions in terms of gas usage. - -The **purpose** of the research is to find out whether batched meta transactions **spend less gas** (per meta tx) than a normal on-chain token transfer transaction. - -Note that this research uses an implementation in form of a function called `processMetaBatch()` which **extends the ERC-20 token** standard. No other functions or contracts are involved, nor is there any usage of zkRollups or other L2 solutions. +This proposal offers a solution to relay **multiple** meta transactions as a batch in one on-chain transaction. This reduces the gas cost that the relayer needs to pay, which in turn reduces the relayer fee that each meta tx sender pays in tokens. ## Abstract -Gas usage of batched meta transactions is affected by **many factors** ranging from the batch size, to the amount of expensive SSTORE instructions where storage value is set to non-zero from zero. - -In this research, tests have been made for various scenarios in order to determine gas usage and figure out **which kinds** of batched meta transactions are the **most cost-effective**. - -The results have shown that batched meta transactions make the most sense in case the receiver has a prior non-zero token balance and the sender has a prior non-zero meta nonce value. - -The **M-to-M** batched meta transactions use case (many senders, many receivers) turned out as **not economically viable enough** in terms of gas savings. - -On the other hand, the **M-to-1** use case (many senders, 1 receiver) showed **promising gas cost reductions**, while also having good potential for real-world usage. - -## Contents +The current meta transaction implementations (such as Gas Station Network - [EIP-1613](https://eips.ethereum.org/EIPS/eip-1613)) only relay one meta transaction through one on-chain transaction (1-to-1: 1 sender, 1 receiver). Gnosis Safe does the same, but can also relay a batch of meta transactions coming from **the same** sender (a 1-to-M batch: 1 sender, many receivers). -- [Motivation](#motivation) -- [Specification of a proof-of-concept](#specification-of-a-proof-of-concept) -- [Rationale](#rationale) -- [Backwards Compatibility](#backwards-compatibility) -- [Implementation](#implementation) -- [Security Considerations](#security-considerations) -- [Test Cases](#test-cases) -- [Types of batched meta transactions](#types-of-batched-meta-transactions) -- [Gas usage tests](#gas-usage-tests) - - [Benchmark](#benchmark) - - [The first meta transaction](#the-first-meta-transaction) - - [The second meta transaction (and subsequent transactions)](#the-second-meta-transaction-and-subsequent-transactions) -- [The economics](#the-economics) - - [M-to-M example](#m-to-m-example) - - [M-to-1 example](#m-to-1-example) -- [Conclusion](#conclusion) +This EIP proposes a new function called `processMetaBatch()` (an extension to the ERC-20 token standard) that is able to process a **batch** of meta transactions arriving from **many** senders to **one or many** receivers (M-to-M or M-to-1) in one on-chain transaction. ## Motivation Meta transactions have proven useful as a solution for Ethereum accounts that don't have any ether, but hold ERC-20 tokens and would like to move them (gas-less transactions). -With rising gas prices, meta transactions could also serve as a solution to avoid high gas fees, if batched together in one on-chain transaction. +The current meta transaction relayer implementations only allow relaying one meta transaction at a time. -This article explores the implementation and economic viability of that idea. +The motivation behind this EIP is to find a way to allow relaying multiple meta transactions (a batch) in one on-chain transaction, which also **reduces the total gas cost** that a relayer needs to cover. -## Specification of a proof-of-concept +## Specification -The implementation of the proof-of-concept is pretty straightforward. A user sends a meta transaction to a relayer (through relayer's web app, for example). The relayer waits for multiple meta txs to arrive until the meta tx fees (at least) cover the cost of the on-chain gas fee. +### How the system works + +A user sends a meta transaction to a relayer (through relayer's web app, for example). The relayer waits for multiple meta txs to arrive until the meta tx fees (paid in tokens) cover the cost of the on-chain gas fee (plus some margin that the relayer wants to earn). + +Then the relayer relays a batch of meta transactions using one on-chain transaction to the token contract (triggering the `processMetaBatch()` function). ![](../assets/eip-3005/meta-txs-directly-to-token-smart-contract.png) Technically, the implementation means **adding a couple of functions** to the existing **ERC-20** token standard: - `processMetaBatch()` -- `nonceOf()` (optional) +- `nonceOf()` You can see the proof-of-concept implementation in this file: [ERC20MetaBatch.sol](https://github.com/defifuture/erc20-batched-meta-transactions/blob/master/contracts/ERC20MetaBatch.sol). This is an extended ERC-20 contract with added meta tx batch transfer capabilities (see function `processMetaBatch()`). @@ -133,33 +108,12 @@ function processMetaBatch(address[] memory senders, } ``` -As you can see, the `processMetaBatch()` function takes the following parameters: +> Note that the OpenZeppelin ERC-20 implementation was used here. Some other implementation may have named the balances mapping differently, which would require minor changes in the `processMetaBatch()` function. -- an array of **sender addresses** (meta txs senders, not relayers) -- an array of **receiver addresses** -- an array of **amounts** -- an array of **relayer fees** (relayer is `msg.sender`) -- an array of **block numbers** (a due "date" for meta tx to be processed) -- Three arrays that represent parts of a **signature** (v, r, s) - -**Each item** in these arrays represents **data of one meta tx**. That's why the **correct order** in the arrays is very important. - -If a relayer gets the order wrong, the `processMetaBatch()` function would notice that (when validating a signature), because the hash of the meta tx values would not match the signed hash. A meta transaction with an invalid signature is **skipped**. - -### `nonceOf()` (optional) +### `nonceOf()` Nonces are needed due to the replay protection (see *Replay attacks* under *Security Considerations*). -The function `nonceOf()` is optional because if the meta nonce mapping is set to public, the function is not needed: - -```solidity -mapping (address => uint256) public _metaNonces; -``` - -This is the approach that Uniswap uses in its [UniswapV2ERC20.sol](https://github.com/Uniswap/uniswap-v2-core/blob/4dd59067c76dea4a0e8e4bfdda41877a6b16dedc/contracts/UniswapV2ERC20.sol#L19) smart contract. - -A more **appropriate** approach, though, is to set the mapping to **private** and access the values via the `nonceOf()` function: - ```solidity mapping (address => uint256) private _metaNonces; @@ -170,23 +124,56 @@ function nonceOf(address account) public view returns (uint256) { } ``` -> The EIP-2612 (`permit()` function) also requires a nonce mapping. At this point, I'm not sure yet if this mapping should be **re-used** in case a smart contract implements both this idea and EIP-2612. +> The EIP-2612 (`permit()` function) also requires a nonce mapping. At this point, I'm not sure yet if this mapping should be **re-used** in case a smart contract implements both EIP-3005 and EIP-2612. > > At the first glance, it seems the nonce mapping could be re-used, but this should be thought through (and tested) for possible security implications. ## Rationale -The reason for this EIP is to research the economic viability of batched meta transactions. At first glance, batching (meta) transactions seem to offer significant gas reduction benefits. +### All-in-one -If batched meta transactions do provide meaningful gas savings, the concept could be used as one of the approaches in Ethereum scaling. +Alternative implementations (like GSN) use multiple smart contracts to enable meta transactions, although this increases gas usage. This implementation (EIP-3005) intentionally keeps everything within one function which reduces complexity and gas cost. + +The `processMetaBatch()` function thus does the job of receiving a batch of meta transactions, validating them, and then transferring tokens from one address to another. + +### Function parameters + +As you can see, the `processMetaBatch()` function takes the following parameters: + +- an array of **sender addresses** (meta txs senders, not relayers) +- an array of **receiver addresses** +- an array of **amounts** +- an array of **relayer fees** (relayer is `msg.sender`) +- an array of **block numbers** (a due "date" for meta tx to be processed) +- Three arrays that represent parts of a **signature** (v, r, s) + +**Each item** in these arrays represents **data of one meta tx**. That's why the **correct order** in the arrays is very important. + +If a relayer gets the order wrong, the `processMetaBatch()` function would notice that (when validating a signature), because the hash of the meta tx values would not match the signed hash. A meta transaction with an invalid signature is **skipped**. + +### Why is nonce not one of the parameters? + +Meta nonce is used for constructing a signed hash (see the `msgHash` line where a `keccak256` hash is constructed - you'll find a nonce there). Since a new nonce has to always be bigger than the previous one by exactly 1, there's no need to include it as a parameter array in the `processMetaBatch()` function, because its value can be deduced. + +This also helps avoid the "Stack too deep" error. + +### Token transfers + +Token transfers could alternatively be done by calling the `_transfer()` function (part of the OpenZeppelin ERC-20 implementation), but it would increase the gas usage and it would also revert the whole batch if some meta tx was invalid (the current implementation just skips it). + +Another gas usage optimization is to assign total relayer fees to the relayer at the end of the function, and not with every token transfer inside the for loop (thus avoiding multiple SSTORE calls that cost 5'000 gas). ## Backwards Compatibility The code implementation of batched meta transactions is backwards compatible with ERC-20 (it only extends it with one function). +## Test Cases + +Link to tests: [https://github.com/defifuture/erc20-batched-meta-transactions/tree/master/test](https://github.com/defifuture/erc20-batched-meta-transactions/tree/master/test). + ## Implementation -Link to the implementation (along with security considerations explained in the README): [https://github.com/defifuture/erc20-batched-meta-transactions](https://github.com/defifuture/erc20-batched-meta-transactions) +Link to the implementation (along with gas usage results): [https://github.com/defifuture/erc20-batched-meta-transactions](https://github.com/defifuture/erc20-batched-meta-transactions). The `processMetaBatch()` function can be found in **contracts/ERC20MetaBatch.sol**. @@ -204,8 +191,15 @@ The `processMetaBatch()` function then verifies the signature using `ecrecover() The `processMetaBatch()` function is secure against two types of a replay attack: -1. A nonce prevents a replay attack where a relayer would send the same meta tx more than once. -2. The current smart contract address (`address(this)`) is included in the meta tx data hash, which prevents a relayer from sending a meta tx to different token smart contracts (see the code below, under Signature validation). +**Using the same meta tx twice in the same token smart contract** + +A nonce prevents a replay attack where a relayer would send the same meta tx more than once. + +**Using the same meta tx twice in different token smart contracts** + +A token smart contract address must be added into the signed hash (of a meta tx). + +This address does not need to be sent as a parameter into the `processMetaBatch()` function. Instead the function uses `address(this)` when constructing a hash in order to verify the signature. This way a meta tx not intended for the token smart contract would be rejected (skipped). ### Signature validation @@ -214,10 +208,10 @@ Signing a meta transaction and validating the signature is crucial for this whol The `processMetaBatch()` function validates a meta tx signature, and if it's **invalid**, the meta tx is **skipped** (but the whole on-chain transaction is **not reverted**). ```solidity -bytes32 msgHash = keccak256(abi.encode(sender, recipients[i], amounts[i], relayerFees[i], newNonce, blocks[i], address(this), msg.sender)); +msgHash = keccak256(abi.encode(sender, recipients[i], amounts[i], relayerFees[i], newNonce, blocks[i], address(this), msg.sender)); -if(senders[i] != ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", msgHash)), sigV[i], sigR[i], sigS[i])) { - continue; // if sig is not valid, skip to the next meta tx in the loop +if(sender != ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", msgHash)), sigV[i], sigR[i], sigS[i])) { + continue; // if sig is not valid, skip to the next meta tx } ``` @@ -260,10 +254,10 @@ A malicious relayer could scout the Ethereum mempool to steal meta transactions When the `processMetaBatch()` function generates a hash it includes the `msg.sender` address in it: ```solidity -bytes32 msgHash = keccak256(abi.encode(sender, recipients[i], amounts[i], relayerFees[i], newNonce, blocks[i], address(this), msg.sender)); +msgHash = keccak256(abi.encode(sender, recipients[i], amounts[i], relayerFees[i], newNonce, blocks[i], address(this), msg.sender)); -if(senders[i] != ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", msgHash)), sigV[i], sigR[i], sigS[i])) { - continue; // if sig is not valid, skip to the next meta tx in the loop +if(sender != ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", msgHash)), sigV[i], sigR[i], sigS[i])) { + continue; // if sig is not valid, skip to the next meta tx } ``` @@ -304,338 +298,6 @@ This addition could open new security implications, that's why it is left out of **The other way** is to keep the `processMetaBatch()` function as it is and rather check for the too big due block number **on the relayer level**. In this case, the user could be notified about the problem and could issue a new meta tx with another relayer that would have a much lower block parameter (and the same nonce). -## Test Cases - -Link to tests: [https://github.com/defifuture/erc20-batched-meta-transactions/tree/master/test](https://github.com/defifuture/erc20-batched-meta-transactions/tree/master/test) - -## Types of batched meta transactions - -There are three main types of batched meta transactions: - -- 1-to-M: 1 sender, many recipients -- M-to-1: many senders, 1 recipient -- M-to-M: many senders, many recipients - -Right from the start, we can see that **1-to-M use case does not make sense** for this implementation, because if there's only one unique sender in the whole batch, there's no need to sign and then validate each meta tx separately (which costs additional gas). In this case, a token multisender such as [Disperse.app](http://disperse.app/) can be more useful (higher throughput) and less costly. - -The *Gas usage* section below will thus focus **only** on the **M-to-1** and **M-to-M** use cases. - -> There are two additional types of batched meta transactions: -> -> - A batch where sender and recipient are the same address -> - A batch that has only one unique sender and only one unique recipient (but both different from each other) -> -> Both of these examples are very impractical and are not useful in reality. But the gas usage tests for both were made anyway (Test 2 and 3, respectively) and can be found in the [calculateGasCosts.js](https://github.com/defifuture/erc20-batched-meta-transactions/blob/master/test/calculateGasCosts.js) file in the test folder. - -## Gas usage tests - -Gas usage is heavily dependent on whether a meta transaction is **the first transaction** of a **sender** (where prior nonce value is zero) and whether the **receiver** held any **prior token balance**. - -The gas usage tests are thus separated into two groups: - -- **First-meta-transaction tests** (initially sender has a zero nonce, and a receiver has a zero token balance) -- **Second-meta-transaction tests** (sender has a non-zero nonce value, and a receiver has a non-zero token balance) - -All the tests were run with different batch sizes: - -- 1 meta tx in the batch -- 5 meta txs in the batch -- 10 meta txs in the batch -- 50 meta txs in the batch -- 100 meta txs in the batch - -### Benchmark - -A benchmark for the following tests is gas usage cost in case of a **normal on-chain token transfer transaction**. - -There are **two possible benchmarks** and they both depend on whether a recipient has a prior non-zero token balance, or not. - -In case a **recipient's token balance** (prior to the meta tx) is **zero**, the on-chain transaction cost is **51'000 gas**. - -But if a **recipient's token balance is bigger than zero**, the on-chain token transfer transaction would cost only **36'000 gas**. - -### The first meta transaction - -In this group of tests, a **sender's nonce** prior to the meta tx is **always 0**. - -#### M-to-1 (to a zero-balance receiver) - -The M-to-1 (many senders, 1 receiver with a zero token balance) gas usage test results are the following: - -- 1 meta tx in the batch: 88666/meta tx (total gas: 88666) -- 5 meta txs in the batch: 47673.6/meta tx (total gas: 238368) -- 10 meta txs in the batch: 42553/meta tx (total gas: 425530) -- 50 meta txs in the batch: 38485.5/meta tx (total gas: 1924275) -- 100 meta txs in the batch: 38025.83/meta tx (total gas: 3802583) - -A further test has been done to determine that having 4 meta txs in a batch costs 50232 gas/meta tx. - -This means that the **M-to-1 use case beats the benchmark** (51'000 gas) in case of 4 or more meta txs in a batch. - -> Note that using 51'000 gas as a benchmark in this example might not be entirely fair because only the first meta tx is made towards the receiver with a zero token balance. After that, the receiver's balance is non-zero. -> -> Hence, the next test is more appropriate. - -#### M-to-1 (to a non-zero balance receiver) - -The M-to-1 (many senders, 1 receiver with a non-zero token balance) gas usage test results are the following: - -- 1 meta tx in the batch: 73666/meta tx (total gas: 73666) -- 5 meta txs in the batch: 44671.2/meta tx (total gas: 223356) -- 10 meta txs in the batch: 41049.4/meta tx (total gas: 410494) -- 50 meta txs in the batch: 38182.62/meta tx (total gas: 1909131) -- 100 meta txs in the batch: 37875.83/meta tx (total gas: 3787583) - -The **benchmark**, in this case, is **36'000 gas**, because the receiver already has a prior non-zero token balance. **None** of the batch sizes goes below the benchmark. - -#### M-to-M (to a zero-balance receiver) - -The M-to-M (many senders, many receivers) gas usage test results are the following: - -- 1 meta tx in the batch: 88666/meta tx (total gas: 88666) -- 5 meta txs in the batch: 63031.2/meta tx (total gas: 315156) -- 10 meta txs in the batch: 59833/meta tx (total gas: 598330) -- 50 meta txs in the batch: 57298.86/meta tx (total gas: 2864943) -- 100 meta txs in the batch: 57032.51/meta tx (total gas: 5703251) - -As you can see, the M-to-M example gas cost (per meta tx) in this case **never falls below** the benchmark value of **51'000 gas**. - -#### M-to-M (to a non-zero balance receiver) - -In this example (as opposed to the previous one), the recipient has a prior non-zero token balance: - -- 1 meta tx in the batch: 73678/meta tx (total gas: 73678) -- 5 meta txs in the batch: 48038.4/meta tx (total gas: 240192) -- 10 meta txs in the batch: 44842.6/meta tx (total gas: 448426) -- 50 meta txs in the batch: 42310.62/meta tx (total gas: 2115531) -- 100 meta txs in the batch: 42032.75/meta tx (total gas: 4203275) - -In this case, the benchmark is **36'000 gas** because the recipient had a prior non-zero token balance. As you can see, the gas used in this use case **never beats** the benchmark. - -
- -In this group of batched meta transaction tests, none of the use cases beats the benchmark. Even the first example, M-to-1 (to a zero-balance receiver), cannot be considered as successful, because the benchmark should really be 36'000 after the first meta tx is processed. - -The main issue is, of course, the fact that it is each sender's **first** meta transaction, which means that the sender's nonce has to go from 0 to 1. This SSTORE operation is very expensive and takes 20'000 gas. - -Updating a non-zero value (for example raising a nonce value from 1 to 2) is a much less expensive operation. It costs only 5'000 gas. - -Let's now see the results of **the second** meta tx gas tests. - -### The second meta transaction (and subsequent transactions) - -Note that in this group of tests, the **sender's nonce is a non-zero value** (more precisely: 1). This brings visible gas reductions. - -#### M-to-1 (to a non-zero balance receiver) - -- 1 meta tx in the batch: 58666/meta tx (total gas: 58666) -- 5 meta txs in the batch: 29671.2/meta tx (total gas: 148356) -- 10 meta txs in the batch: 26048.2/meta tx (total gas: 260482) -- 50 meta txs in the batch: 23183.1/meta tx (total gas: 1159155) -- 100 meta txs in the batch: 22876.07/meta tx (total gas: 2287607) - -An additional test showed that the **benchmark** (36'000) **is beaten** already at 3 meta transactions in a batch. - -#### M-to-M (to a zero-balance receiver) - -- 1 meta tx in the batch: 73666/meta tx (total gas: 73666) -- 5 meta txs in the batch: 48026.4/meta tx (total gas: 240132) -- 10 meta txs in the batch: 44829.4/meta tx (total gas: 448294) -- 50 meta txs in the batch: 42298.14/meta tx (total gas: 2114907) -- 100 meta txs in the batch: 42032.27/meta tx (total gas: 4203227) - -In this case, the benchmark is 51'000, because the receiver has a zero-value balance. This M-to-M example **beats the benchmark** starting from 4 meta txs in a batch. - -#### M-to-M (to a non-zero balance receiver) - -- 1 meta tx in the batch: 58666/meta tx (total gas: 58666) -- 5 meta txs in the batch: 33024/meta tx (total gas: 165120) -- 10 meta txs in the batch: 29830.6/meta tx (total gas: 298306) -- 50 meta txs in the batch: 27307.98/meta tx (total gas: 1365399) -- 100 meta txs in the batch: 27033.59/meta tx (total gas: 2703359) - -An additional test shows that 4 or more meta txs in a batch have a **lower** average gas than the benchmark (36'000). - -
- -All of the examples beat their respective benchmarks for the second or subsequent sender's meta transactions. - -### Graph - -This graph represents how M-to-1 and M-to-M fare in the case of the first and the second sender's meta transactions. - -![](../assets/eip-3005/batched-meta-txs-gas-usage-1st-2nd.png) - -Note that only transactions where the benchmark is 36'000 are included (meaning the recipient has a prior non-zero token balance). - -## The economics - -Let's consider the real-world economic viability of both use cases, M-to-M and M-to-1, by calculating gas cost in USD for each. - -First, we need to make a few **assumptions**: - -**A) The gas price is 500 Gwei** - -The purpose of batched meta transactions is to lower the tx cost for the end-user, which means batching comes useful in times of high gas prices. - -**B) Ether price is 350 USD** - -At the time of writing these words, the ETH price is 350 USD, so let's take this as the price for our transaction cost calculations. - -**C) All meta transactions are sent to receivers with non-zero token balances** - -This means the benchmark is always 36'000 gas. Having a constant benchmark will make calculations and cost comparisons easier. - -**D) A relayer sends the batch after it reaches the size of 50 meta txs** - -Let's say the token is very popular, so there are plenty of people who want to send a meta transaction and the relayer has no trouble getting 50 meta transactions into a single batch. - -**E) A relayer includes (in a batch) no more than 15 meta txs from first-time senders** - -Meta transactions coming from first-time senders are the most expensive (because these senders have a zero nonce value). - -Since meta txs from first-time senders do not go below the benchmark, the relayer subsidizes them by charging second-time senders more. - -**F) The relayer wants to earn a margin equivalent to 1000 gas per each meta transaction** - -Running a relayer is a business that needs to earn a margin (and make a profit) in order to make it viable. - ---- - -Following the above assumptions, the formula to calculate the gas cost in USD is: - -``` -gas cost in USD = 0.000000001 * 500 Gwei * 350 USD * gas amount -``` - -### M-to-M example - -As per our assumptions, there are **15 first-time senders**. The cost of each such meta tx is **42'310.62 gas/mtx**. This is obviously above the benchmark: - -``` -gas amount above benchmark = (42311 gas/mtx - 36000) * 15 = 94665 gas -``` - -The gas amount above the benchmark for all 15 first-time senders is **94'665 gas**. - -With the **second-time senders**, the story is just the opposite. Each of their meta transactions costs **27'307.98 gas/mtx**, which is well below the benchmark. - -``` -gas amount below benchmark = (36000 - 27308 gas/mtx) * 35 = 304220 gas -``` - -The gas savings for all the 35 second-time senders is **304'220 gas**. - -Since relayers are passing the gas cost overages (over the benchmark) of first-time senders to second-time senders, we need to make additional calculations in order to determine the final gas cost per meta tx for second-time senders. - -We need to subtract the gas cost overage of first-time senders from the gas savings of second-time senders. In addition, we also need to subtract the margin that the relayer expects from this batch (`50 * 1000 gas`): - -``` -final gas savings for second-time senders = 304220 - 94665 - 50000 = 159555 gas -``` - -Next, let's divide this number by the amount of second-time senders: - -``` -final gas savings per each second-time sender = 159555 / 35 = 4559 gas -``` - -Instead of saving around 8'700 gas per meta tx, each second-time sender will only save 4'559 gas (due to subsidizing first-time senders). - -The meta tx gas cost for second-time senders is now the following: - -``` -meta tx gas cost = 36000 - 4559 = 31441 gas -``` - -To sum up, let's take a look at how much each of the users would pay for a meta transaction (or earn in case of a relayer): - -- **First-time sender:** 6.30 USD/mtx (0 USD savings compared to benchmark) -- **Second-time sender:** 5.50 USD/mtx (0.80 USD/mtx savings compared to benchmark) -- **Relayer's margin:** 0.175 USD/mtx (8.75 USD for the whole batch) - -The second-time sender would pay **13% less in tx fees** by submitting a meta tx, compared to doing an on-chain token transfer transaction (benchmark). - -### M-to-1 example - -Again, there are 15 first-time senders, whose meta transactions cost **38182.62 gas/mtx** each. This is **slightly above** the benchmark: - -``` -gas amount above benchmark = (38183 gas/mtx - 36000) * 15 = 32745 gas -``` - -The gas amount above the benchmark for all 15 first-time senders is **32'745 gas**. - -With the second-time senders, the story is the opposite (gas savings instead of gas cost overage). Each meta tx of a second-time sender costs only **23'183.1 gas/mtx**: - -``` -gas amount below benchmark = (36000 - 23183 gas/mtx) * 35 = 448595 gas -``` - -Next, we need to subtract the cost overage of first-time senders and the margin of a relayer: - -``` -final gas savings for second-time senders = 448595 - 32745 - 50000 = 365850 gas -``` - -Now, let's divide this number by the amount of second-time senders: - -``` -final gas savings per each second-time sender = 365850 / 35 = 10453 gas -``` - -The meta tx gas cost for second-time senders is the following: - -``` -meta tx gas cost = 36000 - 10453 = 25547 gas -``` - -This is, of course, less than the original amount of 23'183.1 gas/mtx, but still significantly below the benchmark. - -To sum up, let's take a look at how much each of the users would pay for a meta transaction (or earn in case of a relayer): - -- **First-time sender:** 6.30 USD/mtx (0 USD savings compared to benchmark) -- **Second-time sender:** 4.47 USD/mtx (1.83 USD/mtx savings compared to benchmark) -- **Relayer's margin:** 0.175 USD/mtx (8.75 USD for the whole batch) - -The second-time sender would pay **30% less in tx fees** by submitting a meta tx, compared to doing an on-chain token transfer transaction (benchmark). - -### Graph: batch gas structure comparison - -![](../assets/eip-3005/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png) - -## Conclusion - -The gas savings for **M-to-M** meta transactions (13%) are much lower compared to gas savings for **M-to-1** meta txs (30%). - -That said, these savings heavily rely on a **strategy** that each relayer employs. The strategy in these examples is one option, but a relayer could decide to take a different path, which means the potential gas savings could be a lot different. - -Still, the ratio between M-to-M and M-to-1 gas costs should remain more or less the same. **M-to-1** obviously **does a much better job** at keeping gas **costs lower** than M-to-M. - -Considering the examples above, it's hard to see the M-to-M batching approach as an economically viable option (but, again, a different relayer strategy may counter this conclusion). - -A **much more promising** use case is using **M-to-1** batched meta transactions. This could be quite handy in concert **with other L2 solutions** (like sidechains) where a user needs to deposit funds to a constant address. - -Another use case could be locking tokens for staking, or putting them in a yield farming vault (applicable only if the receiving address is the same for all users). - -To conclude - depending on the **relayer strategy** and the **use case**, batched meta transactions can bring the transaction costs down for transferring tokens. - -But these reductions are **not as significant** as one would hope. In some cases it's even cheaper to send a normal on-chain token transaction instead of a meta transaction. - -Nevertheless, the topic of meta transactions **should be explored further** in order to find **specialized use cases** where meta transactions can provide a **valuable** solution. - -## Sources - -1. Griffith, Austin Thomas (2018): [Ethereum Meta Transactions](https://medium.com/@austin_48503/ethereum-meta-transactions-90ccf0859e84), Medium, 10 August 2018. -2. Kharlamov, Artem (2018): [Disperse Protocol](https://github.com/banteg/disperse-research/blob/master/paper/disperse.pdf), GitHub, 27 November 2018. -3. Lundfall, Martin (2020): [EIP-2612: permit – 712-signed approvals](https://eips.ethereum.org/EIPS/eip-2612), Ethereum Improvement Proposals, no. 2612, April 2020. -4. Sandford, Ronan (2019): [ERC-1776 Native Meta Transactions](https://github.com/ethereum/EIPs/issues/1776), GitHub, 25 February 2019. -5. Weiss, Yoav, Dror Tirosh, Alex Forshtat (2018): [EIP-1613: Gas stations network](https://eips.ethereum.org/EIPS/eip-1613), Ethereum Improvement Proposals, no. 1613, November 2018. - -### Acknowledgements - -A huge thanks to Patrick McCorry (@stonecoldpat), Artem Kharlamov (@banteg), Matt (@lightclient), and Ronan Sandford (@wighawag) for providing valuable feedback. - ## Copyright Copyright and related rights are waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/assets/eip-3005/batched-meta-txs-gas-usage-1st-2nd.png b/assets/eip-3005/batched-meta-txs-gas-usage-1st-2nd.png deleted file mode 100644 index f252f36b617ff093b8ac649bb4b9a2a141a3bfcc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31276 zcmb@ucT`hd_bsd_s34$%A|gdmK&o`5H$g?DcL9}zUK9u|21Er!x-8+i&Xjwgo?)D=8@fLZ!1)PdVw_b5qUnr1$VHe^xO2p@*fvMcz>Uap*W$ z)1gC3Tt_H>PN68jpDR&Tc!(?NFy&9cNy_iP7f>DC{r7^SVw7+GUhw~RoI`&m`rog| z)Zy9hiC|AWf`m!r@SVHFCSez)l`PeXZf|GXU>&V?tqy0C=Ghz>vhv3v(pp+txb&8W!njU5&bRzqDcP zZXX?Cv9!7B80WK|nXVK~F2@f+@zdkJgq$muHznep^t_Mf4iNNa{bs&*6ggAhcm|ae zDbl>t$Kn0su-9e!F8{vO=f!aCPP(SN5 z*OOl5y*l~JecX?{EYrzZ?S$16*a_oQ98dM0JYlR=TBz!PFSt-Qm*T6e9FROz?P^th zIiKFi$jGSUtaHn&6D#tYjT_G_p1y%yMmmp5u_-*OktYsY6H(le!^36PxY^(IkZl)V zfA;gO;cP5^Y0=yoW~Qcz@UAdc@drXvUlq%m#f| z=tLS$mB&k=2=^N{*o>^~l-j zX$*hncD#Sju3f`!3V!p3#i)kdxLdL7_CjH)UR?)UomRF3JiIbxuDamlX42T$*r#UM zv+Y;hQu+x!qB?~2wEdknc6bafp^X+Ye}iEQr%jC`eal3&HScYfzFXhfY5G8xUskMO zD3Ggg+Hl<+4>)qHZdXN9ao@DuCVX=V+b^_^f@zVrKfgRy@6$`3@n+fDEmHNX_EKz1 zQk%XiLqcryYJ6#@4VQ?r48>^IqKflFZ*>!aHL0p_C$H?KYW)acSsS5>KMWp`q%U&|d z3i$5rb629KXJ_l(LN@(m_~srabm2KXZqjTuZBiq>7geI1y9rgC7BhZ|Uu3s>LX;~Q z6@Gu}>_03wM=BwZq#?ChsdBaVfA!sYQ|;oYcxFC7H`Q%|t1fKksF)(Tcbn+tH#Ftp z%t?O&l5aUfkIT`kY*csUm5Da+@%_x5IAzTrA5z`rV_>rDb)QHRU1YgW+`m7;*~{k@fjAeyE;VT;7W_)x@^ zS(7Q=D4$|{ys*XHH3z2v!SO5swqCk>#>Xo3`=?}{_R!>sOeZarfYp ztdpK+>Uwo#nO&!GA0Md}r_?nCk85`K)0ZyTUGdHQHLfp^>G@>j(IVVOHWQT^+VCTr zG^DI4OVik_zE zg|9j972gNE0lwN6nAMV{qgxMLZx$4t6Mit4%ISD>LEgYqhRp z-Lm_=gu&X7_;9pp>E;X8S;cgQ>ju}-@flAH4Gezzm2&hqsO^-1V?*Ks$ENf8rf;Wl z`*n$ErJR&{hP_@)VVQU5ZbkG^wccD~#e|~`2WomArqwkpc z;mQn$Oan=mB92Rj7A0qm1nRstO%1>FcD`yLEJ{bs*Va8gGmrDahx_1DN|1A_w?fZR z?{)b}T?dedWqNs4Gyb<_?qfuWu~9FfG)EwsH)Xqc93#5?X{X35L_ra?J;NJipIdY! z+Lynt>-t-UyCbHHwU*kZ@U`l;?LFmY*9@g|jlxGwBVP)JqQn^MiuuOoD(id~bUOn$ z$a9&IZ%6hfclUyXr4d#4KcvA|YJXXe%r2C}9%scICdfBVFJf}2=^-J+Oh2Mm$ROna zDbH8?R=yZt)53^pW2EBVEMv@%Rg}OxsWJ(wwA=OiW%nkF-7Q62x8>MFUvg;fjH?bt zO-12%4SL+dH7d<~yHOW9Ara+%M7UY=MoLEVWJs6R3lK;B_LyoLDn)c2uIVqHgRs*g z8;{)_yuvRM*Q{WyCEJUlGTo4enEkp-7>|oZEf_|Y_|7S90@to7JT?A?skS_#Qg3eI zR!@pAWSxd^MO`39DhgGRX4i)~QH_w- zN}a2Z1CJ9_PR%O99P1`i=-MW|*lFt;$?}80Pkf{eE2vfD2K?cg83rd)<8usA{Chm^ zg^7NKQqG6mw#%*&_bYnaWXgIYzQ{)ZDxtcXWK{Bi)rH}wh3K0crc|x~!MgC8ap}R& zJifuqKV^ri1E@_ozSAI0~Lf_z2!Hum3Km|r<)Pkv~>b9 zBC0MeT1dG2P{t1)Mc~{Z^T^o0wq$ux)TSJN3zB#YXY{quqVIb=+N@H?Vf<|e>3#*p zi22_`yrvCVzErsO`+X%x$ozOi{8nenZNv(O1b+J0jLw|nuA!+J+8vnu0GBt$eKGpG&8q(CV#>++3|^pvH~wayWumgR9QjJfd|a z>ekAk%ER_YjA8kErQr|e5yT~|@K5mbn-)?K&uFF^Kd07WzQwI=G`Z@4GN|Mz3=*`9 z`8G$G@uC>AO`!clJGWtg;M^>a`}3h)F^83mkt42ha+u3=^+&gMxE7Pslx8d*g?Zi5 zbVhP(OX=;7zVzGwfS0!8qC;{VGd&j#gtM^ zPL-Nw2*1w9*7)YEm+)zDc(7S>X$}!50Gi-Sn3z%^YC|uw+!AvglJ9;aUcf?h7o+{^ z(Ok${NDn@xKq&_%v*wqBy6}j=k@TVMElMfA? z|3n0uA360LGKATV_bI5#H*hNLU3@++u-)|OL$fT{J)?51xNMcorpTewYEjmAAi%^= zQ3OB!#9ci>%kq}F2$Q!rDXwKNAA(7#&$ABuKsvBiZ{riohkaT8g~|JrFqA)>@Kt8; z3N6G^++yXDBUQjXff$A-xKQ1dC!iK`2OWCFnY*j_b?%8}`DjA>Pub3rQTV))?2msl>#@ z6(427B~8y@<_+04eu^8WdbeL2KXIq0dlSwz0QYg;+GHKE&%5Vw_B)%k+OhW^(gZg9T$RfgygE9zQ?kQ zs&CoVsO)P|7-{>!jaKQN7n?MK;nMaRKSG>%ixzYVG&+WzaA^y5?P%Nt&CTc@xG!d? ztkv$d(?X^I^LSh^>W;DChCIoD;-%IUFFmc@Fl}HJ^NlNw?WfWl>m^UOG|f97LX2FPPCThqCou7@;vA)1@h z+lAH+u_73Ces&UiNraz$`1W9t?b9}aLMZxgRDZv zDG%Xzd5{ema;>klMM$>BlE#%u)4f{f`eFY-pQFVa47JZ6!)@}P=u-ePp*73)3~lp1xx9ok$2q2Yae*e_@{0nhn+C~+ziDYoW6H5<=+ov)P-AEPy*tKrOhxEOinqfO zCxXS0?3h~^aFRRu>d{@C-yp@Ti&+|rk*S5Gez$(|e3nRE=%~jI@dG8_)8dJu#u0Y} zLrtI@KgAntSjTH_td{7J5#8H<{;CPd)k_=L?J(3~hs_$VX&GOoag$2!viSW}2FUz~ z!sKew84z~z&1Uk4bM(p@TSxAzHH&PIGdDNO#s%CnCRe5rTQ&MgAx*~os3y5O{YVe? z;GLD+w^)&H8RMdoO$MqF<;q03j4~-cnrHdQfOy8x(T~|_``%h-t?4V4H_u$aRr)vR z%-FK8)l)+DK(*^C(V2ESMCIy%z9aO4#bie!P?M#!kZ8i5n!crjTK8R}KKRb4KVT&F zxT>XdwnMtXREF6Z$wcCcb3y5lvjpNop_Zg0{ru}7ie&WMMuR;xe@2Dmovn``Jt#;_ z!`lqn`3}4?OyPt=AUfv{1S2*5w#OH|uBUi(zi$=jZ`2sqIbFwlN0PU!HC%N)-R6yI z(8&<&`sM%9lm2(I(|^fDhyLhNf90$H8t1?Cr2ilJ>fdpm*U{cBSPEUDO)f8Jaq~3L zTNbS`vBLhnnWeI3K9p91XNu3n$RLU?0a8R5q6Mo1lBX-r=!yJF9jHRs;1;EDN~sfcoclA0D| zd3paDjzz@MY4*K)7l(iVVw~0X{lsGJ{`OF_)Aq*v3f{G8D<{PbeT^8Cw)1tRc9vtb z5$^TdN5H7)qvFm4V@c6SwX17;ypVgOB6+FYa}#4+@9$5<0{yUdb|lhogL`qXI5{pp zKFBJqqaj7sYb0EHe2(E>zFwKasOP4C!+5@%MpG$iq{2SN++W6HPRG`gw1UGm2$@$6 z&@;uw5tH#dIYwJFm|Sg6W1?SzbJP%q#J>BC5TDYoiUsq5YL zWxma`8#%c7zHx{c3 zkg}3oQulEA`n&?d!c{T%Wxn&=d-ucAf4x(BG)7xtJ~d`Zj<744eHS}PUA5_zJ1A@T z(`gOyP;q-MbGbvjyMnSEGva9U60%)56#j6?H`nL;`{6~&NQLb@I0C`z7Tqp|T0Dc$ zXvWK9+KY|yEImTvv~fdPaaQAr11BEpo4ByDvbr>SVQ9qbLD;if?KLU;|*(#C~N23=-3A-gg^<+72sJfA>xceQWZsE~;%X4S7Z4_vNk-y;k zWc+>=kV!`)de!0i`g63(9ZPC?X4WON@vBpjik@i%-Ng643;8Sf?_Dts4RR!Zc0o2rF8ESe zn*%#@?!CmvyW5+<$jv|BYPM9CCn@@@L1YOH>q}sL`8bb$t@xN2CX#r)=dwdJ-mji) zjt_aTfea_fI3MxCBdX04Mk^gz7$$o0qJv(Xa^6pFyldy&|E&R^&raw=j>#F;#(a6y zq1A6@YWNwMbsv?~;uf0KEjRPd`hj?k8ae$mxBBq@E`A>?;kmuUC(lL6>9f> zB$%jEm74%XrVSNUwP|T~HlgzpbLflql*zAnBrU?;SHld;ErL3qjvfs-nU|2ny-g2c zY)byE#KDg82-FO?-MIk)mU78euBv@l9c=M| zyJBGM&d#%X(l{LVv(aYwpPEDIZqtQBdoVu?e&fO@9(}d{=xivgDt~( ztfrU!lmRynK<}r=GTB^eJ_o8x5(eNJR{3PG>l}N{4w#J;gR1Xc>wH;V??f|uX~d|f zP&)ZA=tN6kQ^`_6qEoVz^Mi**OtF@YzO`%NZSZCwoL^rFK@>sR2r!w?Ix+h4#>Q}1 z#z(j5yH>_OF-7VuR0>-^nW~=+#8!f%Ak;1t+lnrJe1CK#pvbqt#9LP{py(RFn7ZLi zI>`{C>WJ5z+LOJVEf=dCXzU#SPO4daNQ+6&!A^*!4J}o*wK&^+5iU9LXf&Tfkw$=ulP`@LlKeIlpQgooL(neyEqs*-Cp+1a=MPOeS5$vyzcj}9` zCFl^(PZV8#@mZ>6X5ph$AjSkHUw5zs*88&V5m=%T$uY6N*tof4#w%G{OQc9&7vw~u zZZ!pyd}yK3l1|ag#LND{woAihB{@3AxB)d)kF(m%R-Lr4=ei%lTvAsz`nBtiXkVe$ zviPj&Y56nmPGAct4tP8<5Xwqwj*X42F}r7RZPWd7`g9(Cws+C+NWn`OVnMbnvf9bI z@xE~&tS^^*jJuSN?0h+!r)0a)Y)DL8eDQ(qeT-WS8uoJGm8fgMh?vY1F2}p=S}b=w z($ytN<5C>1idklHC_+xs5yj37;#cI7M7C|q^%*Uazs$#8p>~KuX{}3Syy)=K%I*S< zsHD}-WQuyde2y=xRDv_pQ8BJ`$DrS(mlh?8hP}Af9Z(hh`a*AktaW5s()@L*$64WR zzmKSW#`D)dVRF9FLZVB1yD*M=c|Ie(z8?L*zZn)9~S2u`JVL#P) zL4DPsZet8G>%+`HMcv+d3Z+*0Or+u0i*Qhz0OGYD>7Ca@W2P&v?0wDLj8%0cuC>&g zy5;(TzvhOvXjj+HNuYxeqg3A2fHRzlgd#`;87#+PqiicxFQK>_DS&bU+8Wnv}XNR5y~F6WlFN zdXPfMvbiqv@LQ&ta$NLE08qC`EuErjohLGnB!V+JulDooEelB}l$>^Vsyyz_U26si zCt@Rdu~L&n?@e0Vszu6r%=MTpCZR2iJu4#ybDNmR+wsnbQhoOe>>HJPWckAbAz=!O zKV!5#7w^=?1Jk@_X>DPDRHPXi6Qf_qmuf>oFYbfjzg3h2T~gGN>vW-ldGtVBZ+(W z-{0t!G&iV6VBY4ZRC~tLvezZty`vRZgbEv$RWP~(!!iJnHMy2%;b?V{Pa+AqP3)h#V5 z@So8dEu>Gkf+R5G^PeU*p#~ut;C$Q!wf({ zb!Wxz7A(66S_tR7{KZv_m)P50)igBU)C$N=ec>+$o`Re_*XCW%VnQDL{9}Yyqk3nd zM`^ahJIuYo#T}mP_F_3azwww$T>Jim{R(7q>F11Ov|B$Sui)Ai0FfgW=lk}Q@mkPk z*rHKAfOYHCjpaCKB3CT+32V5uDbKo3rwja~)z$p*L0|Sq#3wKxh!(x1{?gX&!pmWi z7zT(IlvQe$a#BB7s`4c8oV0fB*cj^90fH&*V+Yy~Iy1U$7k%%od&KGCT6jmWZycU6 zI}Nl?!iFqnSB~7i#nu1WG~gbg@PmZQ*o~pDdK39gN<4LL-fiq&1J{mOP&HiKV7Luo_@fZg7L+@O0I@n8;rYvZG7+;?FiqhGRi&z*AzwWI>(; zd_Jb{-Bh&2o=0@&@3-uFIu1b-n*+lp`PXQsiXL*nYaa$y{lTd7P#b&ZT{G%h}U z6@Ff{Wo>t@?7eCPM-V2MTjuZE6}d$NFi^+_>O#y2zI5)cxq%#4shQ$oRz!75syv;u(K zP$#8N0JbuAbLWAi&`#<8wupeB;JtP^%3XF(Nl}f&5yz@-1#-zV;@QFkM#Y^c$)eUlg_qc_KYYGR*xxHH zywtxh>G~5DJ;8Chk>h;7Xyid#$A@oMpU1)%O1m#Wj z&PX0Av(^}LM##*bK4=D^V!hDb^2Y}#tpJoqrZfal{vLGBt3tI_{yd*3!8qTS2c4|D}?{2{lok+pi0qHWsciGlQ`y+n=p!<6@M; zAos?`&q;f88&N}C3i0VSzhy`r_>T$UD)Y1D&XA$drLgLfC+SNf{Tx+0xO%?xUu)5(Awvo?)VmNoH#bjz` zN>>tP1vW4z@=A6xvf^yxqvEuge9#EyjZGdPXoyuJGguq<}KT5$%n2AIXx5RqyGv zD>XQqZ;WBvdaiz9Rio_CQ86mkP-|_z^HQj)y%hs;H@>U7A3r~*f|VC1_hOHMOO8X1 ziY=W8ELE6Q!49x>m*E@XDRfY(8TdM_s~sYNtTV{qbFcm5R8!y;&m`^nHJl16!jn?cb#aoU~_zisxdhLc856 zp)Z4Xua03g@IGJWmMD)xS!!Rg)BNR8&v_r=*v9=03(u82wg-IVcHYSAuO}(mf2PXGXaPGc0A^E6w(+u&TT#I#5-c32%EkG( z!8Hfgx8)N!zw?R?O0h5HH0(Be-~9jXb6@_$;SW#v1UO{-T1yfytSn_NhBbK*|N7d= zc>_6L;G%}w-?)QEUkJ62?Luh(-R3L*Ok~c-CfkR3do4D9&`E#dT)j=7ym0KU=Z2P) zt2O{JctHl4!(^!z9#W(KJ2N_~5{g%lLG^oy&n`u?&rkU;-pz)`U* z)ouETcQ*1^#v*%I}Ka0 z181|url`G*vF4xs|MxNm+DEk3mVAZ7HRE>$&`V{ts$WQPjWtUaw3K$rgZ)2?9&iFn z?>ukl&Qn@?o{2+k`@i@9r3~?SFj7F+gWVrxdo#2p1@U0Nx3MalFQEkhHw77kVuO)= zdP8TMR1$q3ZK#-1!Ug85i*T%k1o2#ZM`y-IFc}48E=}|EI}I^Kf`uw)NxrLC;uolp z73W}NyezLE`x5!ja30_k^Ib&W<EH;*#Kq4Y4BTDMyTgcdUKN${lpjKoNR+#U{JagcUzA0D4wA-0O|qGzQ2i`+qKh@s0M9IatsGbeX=^ zVH>7hm!uEGl{U77F*|^(Gk-AP)@V}}#pnn77MEW1 z1AACF)_E5pEB($R%K{oW2vf&{^FVt1yhKlLukIJx_MFlaOc8*RC zx!og;(tCTbmRla2i7aR!y^rB+&)tz1F8I649IRjzB`!yactO+0xv9Pdl@1v6{hQOw z<`sD}uVA1U0C@Or2NCb@zc`Q|vpn7?Tf7eTMSZ@-=dY)nXGcp&CARXd%aD79|4^o7 z7_Dj>2fV0pqffKSaYz`xJ)gUr(7XekyHb^hinuX(oK4apc6w&UESQ0PDLt6u?x-AK zjVjhL&g7{raMZo_3)$)gM?%}j>Ai@n!(-_OkOv}vy~55f)%qVV=pJ{mDf%^l_EF)T z{eLNZq*72&fk~P(aK2y_EUwygI$}qrJF)6fM2hSJ4GX&N+0Ju{4?Y2AIf`t|v}*P% z!9FAtmo1oD+`Hw6n)bFGrCmY3IaupH`^()hIp?{7iOIWoAK>=9=UP{VeLoMCsf^qjirW*kdj;=XJ$T@R-|F&uaD(l}lMk@@zU=$X@u@KpJ_Au# zOBc#Hj4Iu4QlD1tJd61U{fu&@fS=(sXK=Lr9`ulioZ%NW{XCN}Pb^I|<+3sKuj=kA0kkDW% z?P5*SraC#~yOsiubkq@;Xdy|yM%s+*97)nYt8L7UbuCZR2GP?7Bj1LU9Sb&c|5hTt z9ds<3quz#}8ql%>9@A2{g-KsTC2^gTZ`|Q6f809shP6h$;WRB2qrWOSmVtoFG?n$UX~Y<^oRwGRUCgXQ_?0 zRCn2j_MIDST~1N5)?q*mDD?0( zEvqT6c&&CpXK;B`hd2VW0j1-2-Z!giP~hMOB9UiTli?1Z=9<=n0s+w#c0WoDi0;8k z`D2SYAD?waROggO9?orDVLm#cQ?(w=Asm~}qQ2Q`k``^HMay^@XFV8GVyq5qBT=R# z<^Ahn;p+=@_5clu0ICB4lm;W|zZ5-QA{8wJxF%mGD)b4$8K{}GH>>g}@h|6d)}pwp zdk%$20{$aD&oOFH6DS6r*zRt?Qc-yqQvd$VZ{Y0%I?_H+L;5MOUk?Jp3CQh`0-?;} zXL>Nc#dT-C#inNL*wD3izRV}teyU&x@zv!xR{aIU%Jz$kl!`Yb? z2i(g6MLNap-pHk_nEOc1ogc@DK)tRU3smOP)aGkXahguMXcPDHGEFoG>CnsDLz%y_ z)6;c~??>$8ZXIYx_Y0QFLTV%dk!8RynCUQB=OyEyFYCNbZ$FPDqP|0vhhkm z1Hs50tWl~iJK9p$mJ>f1PhbD8OX1In%a|w~BtL)=MLoX%0-mPb;s05l($JuO5w!=j zl-*q6#*JHPU=<#e(@V*j#IR$o|f(Vlfhl9JF2-m;#C!Pt+yn z^rFYa$l}LiUd0RPM(H|(>tq{KiSkg56u5W#0SE0;T!=|bo?hYA=c|9#Vgc#}+=0MZ zdQ7NH4GrVsK=J3!;jiRsX;3#GY$7!hKsu$6ebY!Zw>ZwfqSR2{=Qdv~t}zYUkshmc z5gN);lga|PG?R6P4&cT^GFtPj9BRIU(sX=kzyhE$f<~i@z$-Pv&%P!#t)~!%LG}MO zm+H1E_QiV9vxO$3n@c@OT?*q(;av)o&h?rsrYmPz>L_ec($f?%fNgu3Mo$ak{`MPD z%42^TXMkkbyqTV!_5?hlzByVy)bjjMq&*Tu);=Gz;+!a_%(|zuP5p7!S^4Qk1HMzL~2Be zk5Y?QpLK=kiRUhB_51(VNd) zF^eZwt6plr17y%v%@XZ+rNfvzCTB|oo{7Z9b)`)$LNkrEpEio{$Ku4x(-z}SAIxy9 z!WBPGT>^yAZ|_Un49z_!0$I+WJ{lW1`wgLUD`{b&`#!ei3T?qErUdRzB#bM*_Wa9wRLkNZKtD1^>gT|u&TAN zFDmlag=<=z=BOoK-tI=EP`ye2lS{KIjtn_6w;aTIvA}X_^LX7qCXikpsVsyFpQJLK zqJwUgJE~wO7j&f7N+nYeVYQLKj(i+9<^CjMdn=6k?zbe(H)x`b+$j)BWts#UmWEyZ z*4boNzcLkrr*zr=uI=}@*sSt$RQl>GBzv0qR>vTIFgC?jii`(io}{43W5E2ma?C)& zhDq8=?@|a7X60B}nhMzxsc8el0wu@|bVHZ}l0;F4J<->4hkvh5;qc(Kr8B6W8WqzC zbdrt~!J|Bm^A+WMFOIf4ttT++G2=AOF+jT+o{$o^(o24I1Az%7Hn*DU(13^l749?G zSzGX0TNSkZob1xaFJsoGrl!P2tNkRUAoX|GrA)rPuL7XCJ0#Ujx7mjc*0iCkS3ddkRS< z|2EOG<#ffX+j8onjcrX`+K3>hz$20gI!0!?HUJ8E0J{=s*U)`Oam;xBn>TM(J(*A; zxzbbZ68!f^LF(7A<7Mg&f`Jk{;-yjv! zO@ms$+jAVq2@8i6fqr?Lyzgb-Zmn2~iNxklF*Xm-H`RSH=F=zrUf|)RSaR@Cc6N4^ z1BRdEiurIF)pJGF6n2U(7+JZi%6Om6MEv!J06VLi40t4gXFz0VIe#VA{*xX3#bv<0 z4`&~!n_xvFO^A9*bCrvnm`GTK3r=RN_gKJ5z%dZ(1&(!dDyBxHo|gg&1@lX)Q}NTT zA3n5vFKF>3F0<1@S<tNGariijSGDuI`O6x&57W z;G(irtVx0gC#8LVX+^xe(<*7xnTZzK7%5>c9{S>q&UL4#KLQ;PLYe0(>8b?F=~_KJ z)0YZDaQ`AuqDb&Xx7TdPWyHef_K#hB0(25B+1P0Gy{6#jpXW^F;qYUKZ;blFSn}3CT?@D__`SA){&jhiUD4;oi6BK z6{oETAgJkg3R`^#U?1D5Adqgj(nK@ppITQj?PU|8@hwggD8Oa_KTHxo@S25HfZkZ; zW9$%i8ILEA)NnXX-??n={5KS9@tNdn}dA$#d-(2D$pj+vtx0|diY!Vi1-Z$ zWL^%S@($?p1MZ33Ko8qUkq+xppg4Dt0-Ll;g>4#Q(06kI`tlf~=MmNFVZgy0tI~@m z`((=f#&#{JTeEpw#X`vTx%h>U?3w^H!ZJ0%5rQc_rhR0}@6LDvm~6*(UjF)$R*uHc!Hch9qw$$N{J$&f-ITn|ho9#VLd?ylCk z#x8{}|NWUK=l_hwit3VC6qH@>5Vv3qZG@9bC}Uk#Q8ywz;Vayk!6dO3u>Q?tn!JNs z^df|W-AHe1bq32C<7`VAb~qe8ivR$aFr|ZRvf`c6V1c1Pd$;Y*RVq_DMyMkh#QFn_ z`5Ly?(+C+yK~E;j9cSNGFo7Pgg|6pw=LNh`{SGIm6O)v11>)?o^8C5SfEwb zea_J+O?})i-Bk{75Quy2l-JU=6r*-$q?^kSL~PsMtp8ryK}K+b_x-6E|E35BU1I`Yzm)ISqU14^dk{d?}YrWxO717zW0WQSz9Aiu~XWh#J%qwYM~sY{DKF+5s;oJ<259t#|K zl@m7%ee`XM($EIHt~}w|^|S4Br~l+m7gIg>^u3dSmPY8tJnwU8$;%0I=*!CqcbN3H zZJnZk*wPEp6vQ!Un1tKbtNJC8G`Y!EEw(yHO*ks)q5fc}=Vz_7Z1|4@@c29sI(du5 z0s?whs+PxU%ZVX+E+vh?VM}gWgTA2?5WB>5r&%h2G%SdW=iVF3#^#qtijpWtY?}jc zuK!dt1nv0fF0}6SeHx(Er!}NCrZufg&`Q^w(7aUCWXYMy8z>hjAE*$hh#7zC4-W8A zmwHqgD?uY-`Ynd@T3o8dIz}}}p4d+L?ClN( zhp0KwSOuovXwg|VrOPFwfC9Xj-?XA2u9z-p@ksDEy+QFzD6NY_SDsBcDCJ-!-3{C| zB;gx0RWo~12gFF<$Y_S(%#QpoGkDb%TAnOBA#_G};?_&bw=M%K$`4|rVv zF0`(@D4PYlbMvpxI>!rwitk*5!lj1Akvv7 z4Jyk~L+N3co5{Mb{LxFYl014D^hTcsmHKdnsLn)j-W4^jBhUVV6L$BpT>9A3@+ja> z$-kboGeEPmL7EhZ+|GIXoynv&>2>Q9fAga2>U>8INrWiP^bT8t|DwTdf3OB3KGzoM-jAv*Dzk<=0os+Wb=oCuMZ6a0 z4fuAt(TorJzxyPMTRa??U4&E47`+?nQt)sDyR1Xt>D~S3M;JiA$#+n%#~LY2?FUjg z4#+NGd9{-tLmg?N_m-ekrl0P}OS&{q@pvhkf%=J&oLkLu>dj8Hks!3F{G7VhrP8F~ z;_)chl!m+$F(B>3&c;TmZg?Wv!TzcP-&<84bljGPYo#nJ5VBIEcBzMr z|C6J7{>M3bmJc?u^vgbH4)q+R!fJ3LAjjA}qF{49p97;odeO@Ony8X*JiQ!n((WN& z;k$k*kpJ$to`i~#VC5?yd}Dj)I^V3HfGDh7Djci(h6!5kdN=9NW}rzC97_fTNpI*7 z7$l{vQ?*NEbJ8Hdiyr=B0;MeaQF++gMYrb5woC#~#g9XkznF+M%z)P~=IBwyGvVWn zt_u}k7oEkhWV{6Ax%6Q2P?+A~`>LnCJNb-%7LR9IHys8UR-ly2m>uZ4Dgv#N?KF%W zPL4w*&b4$eL7_G^e|q2*607KWNhoLOW;#XJ-oD5QKs8Z+*$@$v#3{vhDj~j(+QwQz zm>`+o4@_k_vl^Fi_p3OstYoPWYa+kVCpk(kkr{n-+iBzBJ8A0z2(z|^)}{a`Uk zuJ7=P3*3Ra7{B~;9bl%z^@f@`hjPutOIe`}hbx)13L4kJN=`k&tlW~yG#9eMdOT zkk5~QD=K=m=2#S3`7mMe$}5K3Jy{}h2FG$xHnFq@v__WVcd3N~&rn~-b;sX(uK#PD zW_=I=qkMV`k@_NYC=6LP;IaUpBm2ILWhL8GqUm|qjc0~+D579)*Y(jv)h$U~52Y6~x3yR>uXGRJ*SY{U+hHM(Co;N| zFXqG(S|#xJ?2iGpeqaqIGelLATY+tdM^G7x@HIr@!i83kr!Qb3N=EIVCDxWwCj{c@ zFKg9c23RB$>bXS92U{3L$_y82^`Feiwu$5bsUst&bCrui;Lt^P8TP0T)H<`5z%#-4 zGt5L`Vi}^N4K}e0uhcHxOL==`G)ylgo$ph=JM;f)?JK~d>bkZO5JbuXL?l#FN>D(_ zQ65pGMY>dG5McmmkbV$&q(vA)N>Ug?hLScYhn8-UQo3sf_}BQp-}lD^8v}OgMHvWNPw^;8pHR?lSofDn=3`n@e0TLV$0$|1F5psP2 zQIp{^?dsPjD5YSTy7mI+?0@TTc9Hwww9ZwCwSrx23)O9{GS83l(`leMOq< zrsI@E`UBU4xjqFPYbJSO<)PlneP5L_*37^Qo%2Aoyo$dNa%djQ^RBo1%@BXPv%1oZ36M$v1kKoyzKTzbz9l z@-t)TZoq8nYpO^64z$wl63I8S6L7??)%^cF7SoeH80cr-0`Q1 zpLnZ08Wm0liaB5GPNXX4BlTOB2d>JxD5e7qn@ZYttU`3oKTPcL6JfXRNps~exD-iq zX`Kk|JwoG0=W#LmWMkxS7vnO1WGe_YRSH}8->0C&Tt?cO}A&wm<4 z*X3h!RM)mnM?Y{utlf>6OLY|h@R=Nh6fdy94ZYI$nPM={pm?OG_=$$hVoCP`;IrR1 zgs==}D8F6+o?{Vkgh)^LdrToO7iqKKp{KVqx(#FSmL-A7Hl41kL{v2+jUwvZ%8c{{ zt@Y+tU%rg)&tLs1cj~2j2E31t=yDiPFT}_V22S2N|7hHET`j)})=D&qu$8pcaRAL& z0P2!=ep8l4imd`+umk?IU9O%aJ-9Sl)h!M91SNL-ObXLEEc&<0Ubt|>q9%ea04Lw1 zXV;u4o9Z62;LBauJ?#hX4q?dn3AYt*&Pvv&(mN6Fenld^Bq`7ocVR+>o@}=2^6hk- z=~=RHgz&#ht5{RUrejEO@B*L0?n`!v@04S z!LN+grRX79J>Bm<5eEITV0Q4oTu8h|3P#z7QX|j&**#Z2Z9xzsbJG!Mkafe0<>RJ; zktEK{5b)#d~c#C{)Di6UL?& zll)_@Z_Ta|b@~?%3-~x_0?OYMta$ktCD{)j^fioLVp&Q>5`T934v#Y&{kUU8*7+wz zypTy{4`AZ0NxrG~{@$RTnO96-hj!Qq3Eyv2YNeBpkhJXNnjfifY;&Jp8WrJUVrI@l zk!qv_DPN(Q3uo~1H=5~rlRBqrp-TLzG4>J+l(-&a?wn)J_i&GMV!Y*LM)rL^6;q&R zCu=@$SJ+f-R3j$ZHicm9CdhKfo5CitRwP#``pq*N?>kNi=LRX0A+8=n-Z!lA*F!`> zI*C^)kLUyDYt?$YjJ2E(s5=!w1S=C|T8$uys_|wi-I#8z?1CI{ z&Umpz%BI>5QOBIx2(?XN!Y{b6PHQA?Ek51cBb0rcHDw@8;Ps?B?Gx2;!SVT!4h7eg zI;S3)GGdz^dfHJD-FrG>u)n5ixYD+KDA1^&I5B+Drseh%%HwuM2hYMiM)!to-!Ck= z4kQFEJ1!HZX%%gDSNet5_qRu8y~XS}=BZDg)_$ENX*1L#PCmG`IJ~$wUs%4sH7sf@ z(*q$WqYuv>8Oj&BE{{!kd`P1h{OCuKuM#WbY*ic_64EUmaZdc&?HFqgnqGh~#>@wC zdw=?yiOUtx&gPt-(f$i@DZ?UUVuH*<-LdW5=*QuGPS-Z}-UYFE4&L6@``h@O8TB^N zUOMeIvC$8<>$4v$684PAQUlSV6>E4w6Ybm1-V*_@AVW~w=cSk9^qGe5L&wYHe+J2? zR3X2fVqxGRVOuP5Z}X)8g5|&8>r@?L^gH9O4df9ZwvFhfw>w&8+;l;t8l_4@|8ak@ zlWflN5BBg6E6gR?UjZ;^{;6VRYw^mFxnm7%(MA;BSXUKNmL*bp12pIERes*25AwByWAM%Es!EOm8a3RKYCs^=5?OrR_Hw0~J z!Co(_PU=K?<0I|Z1Ci=c*Vy?vGn0dCWE@$e8wG-kb_qCQC1U1{J;yJdJHH31@u5jS z)oc2twcUQy9G2`dE>04zBp{69YX+2&QjlW2^uFdSCrz8Td=DY*)*vnWtr~H1-_J(Q zzV{>Vrv^)?`dW2dYj#l#qS3T5-8gGUcbY7uYPq zTpqjAvH8{2s4=5k&@H1AECqQqsPztU!8T>$MG3tJ#kcKFJe7Dt>05&tsf7ZiRi7?M zgngR%Jp7&SoMfZX=DLX+*4wL9Y)n^(e)F2a{w@h0Nv@Z+soZgsmH~M#d!AZh$B*C& zn{Y5m>cu4I_F%6cW5BNQdmMPIN!(LSe(b@#V04aoggs-A)7I(|JHXviSC^OXshBgK zUU^`qXP%XCm1RssUU22gkqVzZlh3oTx$KC3XTkk^E%3rI@yse3KEQnAu92uL=(Yrj zg26N@RntnR9GlU~-p$&(ToehZb0+{cvSx5NZ`JOp^*6&O?)=K^Ll};-Q}(k_=p*v` zVvR=H$r~ONYUAN37NmokGPdP$4MvCoQk>>6hwlyoRS9a zj!l1o$rjK;28)_F<~g*tSAy7G&cc>4_ww zk$TIU*HjUoA`fUZQunDsQ!g~KDT*|oDWT!ho&bf2*88j;h~ z0Ok}7c@_tr+2qvU_a>f$@#d1>dlGJD#HytV9Vy`#p5VZxwq2|#TKH47K;Y@eA;Dg^ zqd6DWss3OTui(vxHdr0=e=(J6PB__Y=*A@|C|C?^?%~D=PEK$1N8clmwYvpy};o`m%)(#&cW3R{N?U{S1>gu zMl+c#L9X!v1)z`0?j(7xeYNK!XT8W2t2>D8R#^+?22C>Ma8@d@Hft;&P035f=_a$_PzEyOY6H9-x4iH?%0qG8~}sBHVp+Ovs)fOafG?|+`B*u0qYd7O&tdOBZcU^ z&gPl6{=JIFzCRmF#ZuwSuwuQlfLl>^+{kFU(;=81`F*%rg2`pKdo{v+$jAP|DQ}y$ z!KV}{#GV6}@rAhVOA%gH^ZkpdsfG?*AtV;R3lOJHH-Dd6c$d5VaY{`id|d63M1W@5 zqd4sE-9XhLOD>zIb5NmX*3xRPns?L^t7+6TuWv`mdhz5hLy6Tw6MGq&O3gu>W_I~b zrP!B!IkEBrneQVb|0D>DGV>XyJUFe=%oo`!?l{xB@(|ifM||e`nf;}d7p{8b==H2d zIhzg+CI(bMh+TOiQQW6+)YRhkVZ|kYHGcXTG-`fR-h-ItFh1X{&56NP$IT_x;&Vz= zsF`;SQwlf@RpZ5Y5_^7p>DbGNR9K!rjt|Wl`_*QUSsUSgNj{yo4i?Wco8i8M-+2X6 z`dveA^Nb%|c#2?vs+!&0jSY%niCs+=ygaLWrpbU^&~iV++@p)f4+ofEV zK0E;lR4)yq`3*N-6uzGH6Frr|P=I)Sn*=u#epb1gbGr=nO-m$Nn8UHmWNS*Q)(m?h z>k2@LpY=_4(L@WJCjDridY$kIR3XR>RK0DLHnUWyUPzliv@-0j5fv#*R90|!i{7u7 zbeUZ@BX}>S1fh!p7>U5akudknT#kI6GX4nR>#wcQ$CtI29q#X+wBqC$C~ltXQ<-Y! zdoIjxAw6y`<)Cx?a4+NSi{Hd2-c9al*C#k9ucJr%9>mO$a0w#OzwC5Ytqu$Gg`^;; z3Rr2_B6gaKy~~!Vn}6NNO);0Ae0`oR>XO5^1|F`Hb?gQ?lID{xl?{sf7Eg3`n^=?~R zMi(D9DJ&Ja`Kz06qyfl&|6&a4PBot>6Dj|e#MLzXiZ0$5AD&V1j{hAE>gqv?&U6RE z2V5&7DZRP%)Bf$vO!F7SJqAr554j$>8{hi}j;>M%_I)j-+B-_TuU1R-E`nugJkFpo zPV3m2wRtulZHlm2CWlt*F2991^Y9`G>%IX{y|p2El)y0@>dQA;j8tT}5c#%UxkUZ> zHKmY*V^2>gN-TcQb-en(;4xEt{|i#Q|C8ci`*{dSLGVAqzYU}I*X}imX}6u4&b=u*{$;3|f_+JMXA5DEz9iR>W7u~alNVoZXi0AX82SBE_mGkX3w z3Pdw{FTUO@) z(fxH2U%Lbwl3wlUy$hel5o*l60C-YWW9`i->I;AO+~>7i(4T<$6BdnZNVf=uCrtnk zq5kt*^rru(@rUcN7GB|u0piYkCs{v=HwFGi-dH~M6S{Qii}(7Q@qw3o$(G>PJ9le% zubsB;&1LeVLkR1<8FyA=G2w5S;~>)a&>wWtD!x@6oy5NJ)Y4W8xJI^fI9$cak8N=< z``%JnazgX^OZ%HWEw}5>I2^@TA_K9*_=|ey+(jPgb==nuUcxnJ&ivxNU>K`{d5+<; z>(>?()+*%5%8KRgddK~Mn`wfd*DsiO@=>(H7e{yR;hJ~_Vth?JJ;nNN-lj&uv0=2W{sd`C#fz|HnV-Uy3=;^_-RWbknMgI|K#VN(5C21FCRL$H`QPAu`#= zrHhz;+5O?hB8#2%mi@L=dCb)V0-Es(S!V^g0g$oN-oCwH>b2Q>?@0sXA{rsZ3Q_uD zMiiEFlo_8ajlEu#*QQ%{e)YB3$=4AtcZRCUjuxLc_!dWfZ?-w6B;c^apPp=C+>Zo^ zDnfpZ`T^{=?Qjr<5$nq{I1OB3mS$h}Ae@9xs9MB^XaKH)6DuDbqry@y#mjNtzDe&M zPgsY-`PHF|qpU}K_pe5(#f$S$(Vf*K5`Kh;hClie*dUOdcq&~f46-CiK{)3Q8(Nf) zyx8L}Yh^wT7?GJlq|9;DFk9?_V*S*1tZt{bw`sjx>>XJL#ro5(7(BaPt$w8$nXea! zx4Ey+Fdeor??{cgnX7_G@b&YCTof+97GurV6DRLMw$}%H9AywSAnvrkQ+)Djw$g~R za=q|j>6zMtCg1y~Bg?4D(I*@hsV^N&YiE9U8F#&Suu`Y8xNY{ly5tr$S*I2`D>>@| zCjSC@oijqTw81CCr^um?cW_Rgq9^)orWb133n>$2axPZR_h14KpG|RTWn)s*}AWRju%9-9yl}z z>9w!Tmr0aNKRn_cc)8(U*39-p^fj5uOEI@ac=O-nouD<1ran-JX2 zolchcT`o4e){D@%Hr=-EiKHchqPHwSec0rlZ=7iMEgQz=Tu;e6g*PQ^*6ts^#=2G< z$6y~-T*hF{-CYblmh3z>c%hWkVk#U&3mQn#&;_qumlS!gU?11TAssG?Tn1EFhgbd? zyoHM}!|SnSi9Fkyy2Wss(q%is?3Xvob}ip6Al1C!Q44&PAGz3q;PnoL zIyVCFEJSRV(bRv?B0Ig$rPP(2!k;_by2N{pOCQrdoEtJ zgfo*(5fRwJTIpn;gI&B$hwM5KqI)>-WmH8Mqixv3RBD%xJjHH}jAO#?8$ug)q)BZ^ zrxd3Ye`n24ARG$lehtsE7jBgb?S`Cl848A3F9F(CMD9Fg;5meDr z^0<5agn0!fLhI#n388S|7Q0QZUX>-g7T<3UK1Rv=WeV{B-dZ;K33qA)7sRM7-lC^l z)7Bpc;uh-l8Bn*e#5;R;(1wdQhu)CBaHQYCXSgoBz{_WtQGUqN$B3%@IrP!PxN${q zda?mM^1(oQw#Qv*-$V<;*rbjl5ni_j=kAzy=Z(S0$96w%3HB&o6f^P+ptdxNL`8|V zKdq?~*2}aS9G85m34P_Wi&}&h{W0S;dyk9EX#=!9dUMapxS*YY33EzmZ+n>&d`qb3 z9)z(wm;@hZ7ULNTC~;}Gy}vwW>^w;2APi^G*}xFyR9*D;dRl+D|NNKNjWzRiNAaIA z<9Z@kO5bp15)LLW?#iQEd7wjnO3AkJSJqjv$1h+Iq@wq0m&>kfwKuQbmVTAAXxHM< zWVKzsXsJ57Cu8#|^c&uks(~()tn(!K;3sO%^N@0R%B-}u2+A@vNW?zcko}ECO}P%2 z;60YvL-Q^XpBC%7aACXFuz~j@lf8p6+vRfW2x#Zwx?=C5opnWru!2I1u;aAwc4drS z_spTyu(uSoJ;gEPrZ}=W@&f>$-UPfNEY~RnGO%BcJmTEFGtyti*64EGyZ@4;g5-6{ z4g#_(vuHIy`L@hH`b-qorpvOy-;%wx)(a_sjM@Hx+Q}_5#-W0~uEpC9=4FgPuJ2n6 z<5au)>x$#l0P8aWAS*8QM}qcT)vNcosmS?y@YULHIZ1IV%*k3Xd{TaCblxwIk2K?D%Ht5 zizo~XE1jMi18mTK5Ea`1$rKilX8TpG0Xl=uu~_3OI=$lOcKiMn%JBoRh{e1YE<7yL zXBE_KKG@T^o!w}BV_4@Sma^s!HAeo)Cm+E|X-ScNd$hson~U65Rdo?9G4IhoUtQos zeg7&FK3G~*gZ$9K^xmO33M~{Rh^)Ae5wu{f#_irM$ml)wJprSIknE#X&wM%y$743`A_4&7TJsjv>*VW}Vdp>}~Ob7z<;1C@6DJz*D zE^M75gg?t>b`YDEC)UCy)v>Rywe;=?4ZAutKvuJgROm>#P*P=@rk# zde&KT-PfjwQb-x7Jn}U`0b1lWJ!l8DKe}BelHU5Ie7HDNyd&D$P$}N55S~0KuSu2o z$)z+!Wk|W*{mF&nNHxISi*kU2YO&l>PT2URO{{{1GdU|lVy??~YP>H02#v>bL=y%T zJ;evH#g2fKf3vCUHByl|iRp;1H`jM}BWBF{6LUlS6r?zU1)$rnVP@=2qfUZ(J zPb7@`jHQ86{Prk}d0o&b42(kJ`aDYi#a1Lw-L50Nw>^IzrF{(G12OP)KftLFlOWz# zII;x-gCNe~Vdx>n<-QjJPeAubCNZQLE5!>^tF`bu#^j+`Q3bla&?{Is=&b5-x@Q$@ zI?!P{A8#nU+-WOUDW7iU(yfh#H5YZZO>rP)usJQ=w7MMuJRYpn`-Rd#RVLPj=nT4grTBfB~7v$Nt!)!w(d5+Rh zW3|?%lA#OHOUCYX7VcBWZQVIg)V*2dDD(5uPq+kKb;Dw(GvzRLC*k0{VTbyMFue`j5^{{J#2!w%O3GOfuGVettxCWmqG|ZU=*7J3&jA&H}g$TvU z%-{`nkNFxKq$Dpx<)cy!ZW*e)7b&d8G|?YsI&*mtXJ`IIFpE9={!t%? zR9*#{4v!{C>7NCw^Ad7Uv`DfN0ZQj+=pFI?4fz<6`^D%hQ9+Mqt#ks5Wu=7mUfJ%v zXbK#fGPZjD{rQ1Z$4^Br;G5i|J9{N{XB*Tk&wmM|4*_Bqk5bqBYPgA8fw(LOo!PCBOMSmI@6qGcEY|n~WV=PHglC4s3bc~s zBT*GUs@>P`)rm^kh630`3_ywJN$O(=s*fDnPZ2m`UmyKli%nZ2%i*zuviwh?Ey5v$ z_O-i7m!5_s?Y~-Jw9JhW%&X9|bAGLKmv!OL*=hc}#w;xo6dVP&B4ExrSqig7BG)5b z&qbmW_EWI5R*c(2eSaYj1~a{E20M}S`^;^3`-oi=LkPlGuCjElx;<2c#uG*)NilU& zs%|&z2?!+(xE2qcP8qw+(wtrvbLXJoj`M^tTNE+}8CVVuSN>tkbd=GTM_nsZ`8>&# zfQ;TkU@lC-zWOCNk7W+b1`K|5zTqN@T_TD)WuH2ji75AXE)^%0le;j4A-wQmv8wo+ z5Tu*6`S78|ld`rOw!>$aA5;}PHZb^1_dc{QKWvM#tE6XJ}kv* z&0p4)0`dJSxoFaAuE#0uQRE5Y~-r)r(cm7 zDU^SEB);r8@1@u7&?54h&G~?0fRADj6xkkw>|n!@uIVe^>U<9G&E5vhp1JRfu_||t zAO*|=%NK;=vB>3Xm%sKFV{C}SJv!oVVu-u--!6=>jyXt(b~t%VZ{2sZ);EqulXu=E zA2fK9#B`ch^)Fa#^*%Sl*8a>TrBDzON~Pcrr-ZW)2LH(L+}ZkE$U^7|Ucpd5)AP9Y zv9%y`1w)ulmQ8mkGg`_P45#6bb+`5IJ`I7|O{bMl)J+Kz)(HWxJgWeD0~$gL+Fxz7 z1*%cQ2k7yX31LOuXGaGu1m@gm719N|%%jpa{!bRIH1V0-IH&HGG zJ*l2fmZR5&z116P4mYmn8$VB`--!_U-2B0QGVMu6vOS2)(jdtYzciQV>i(*HHWhV1IRT0!TCWYUWOdaZBoNiS$x97KuoM|@vFPtBzF=aqg ze6+QkXSM5fNf;SpwVO64pL1(8aw!w?VXUa6uEOdEc<+U99P>lJfy~4uTL9p?t*gCp zAvMMywqADbs)(2;)hK}{#S9puFWd{^Yr)nhSM(I-j+|`1=e_nir5MydTOP-y~^vUXeOeJ zx*GJWR^jlWYD@p|Y>kw&S1m|VPYWI{&W%PKr!~K@+UX=6)obIAeXM&G_vju~vz1bT zyv44i(VYtJl7v?#Qdh6(UB%T)Z1b1dFJS3)9S%_~6;W-rCz>zo=ILwYVNf*Y~j?LGY-36MI)@XXo#ig-p7XNby{67PpwEVk&`^Yv5l_$68EHjOrAa zGCe9zV8XfHyM<-FJ&Cc>BjCC%m~Q4|ed}S6b=btHb2Kloorb!&e(qs&9M;8LKSVS3 z)pA$)=(0txht^u%T9e_yRxlDACavekHj>_ZqJCK_htw<~r)WmhLJislkY zdkdhRA0Gv=GlQyO1gJ@0WEM8$4h6eK(mxOg3kzHQ?$6i=lln)hKf~pA&Xy}{Tf=r> zb^vZxmR-F&^JcX><=`67V@rMx7C-Tvpf&poL_b+bMMDY7aGIHev16NrJ?QcFEm}j+ z@Sl#0kpkX5VrU;_rh9)t)Q;n*%#Ffh+UIpm~4co<(f%1hE6OOie!WCkMXPQUIu zxhIO5D}|mFOLG_|?ygV%bt#kPL&F5RSR4EAiRb8S7z%J|osHSV%^6fL- z-HIsPzu(l&>lsDR1jj%04u^Y2uT4cE7EzP?3ClDyi_2Q=S<1q=9ZX|%iw($0oqX^Om{m=vf(+R=~|K(TyQHr}XY4pIjks`9B zDgiJa29(SXV2Gqkq~0gR8c3JGQjz}tw@d%iSN>5-t3TZR|6I3!Y0m$jQvSJ9{;&G! zU+VJDrTk0R0*ds1+1vkTrToj7{$qeh!^lc*(6o`X?Ahe+dm~`?#V+McG>rC){pUpT zb((b=$K!sjjDI!JvBFa!Y}W zgO7CUm6R*lCz?sOeoXxA3IE{Mc_GjiWNJF^sCph=XZ!XWv-QJvb&J&X0hFWypnL&J z+;gKkZ?E%!bh4jKa&3fD6FI=3h6Bs~8{=QJG&5&rPRD7)X@m8bG;f6W`SBmqizJ>6 zAh#y|tstOO8YaR4R59hn#$rClz=qBK+Z_qlp5BKu2x|uke}9PsI8U&g`bYKWp2F!o z_MjN4GbU0PDRJ!@dV7+Zk;8bz_H5uI(r@D!+aTd4*Dxa_$>qcxrke4?ko|kGu{=Ib z0W%zGiScN7zP-fWovl&mWRQ5>K8+e)8en|C`1jY53FvpA`$Kx;U{px&A$)X70vj(B z*AcMku~qM~?azcvaf4XX`P0A63aq&eH(t%Kl$yS7 z<(qR?6R)Ebw|q^!Sp|ye!DjbmXpuhq^JbH9bO5r-Ym_+AQ83$Z=`9xi7(OIBs6prEiJ&L;F+$7vio2XSKZ@fm&dIHj$2H9x=N;HB)d$T^S z%+0kMnW7Cg<)gYp!fF#|gtms91WDrmhfa#@A2N&`9Fk~#Qe>)jx6Mvhei@X7g5N3z zHIl+^aJ=EHd2g;x13^P}wH}X+X^9n$SoT`>u!pR3lgHS4@{isOl2m^TfwV}Ux3520 z1i1iUswHWS71PdgICbR4D3fEbRiO&(4gUh|_6K9h z3O?SevI%BA4r<~l?`9>w5>GX!w&CkCYS&^47p_F2=|M?H>M)-!?7kV28j@kjwvT~TT{xxM)rq^K(=6>JzVvPDbYqxCW|{N6QFr+ z2pj0q>(Ny?c{R!6C_IBG^DoGK@tYnwcm3HzB9I?fGnS45uE=r&l#q9pVJCQUe5XYn(bR{ERD)Q$VI1mEo!^#fk>B>N!IvS z!^LUA>lL0FO_3d1n7dPgjx%SfJWTKk+<&*qdWmf3&b5l>*8a9Kkz6>qDr5R zL)I;pB_vO@UC+d2L#2r5?+pkk=F%?E3BP4;)Mrv&t#1rA|2F+by9hJ9>Y}wB@?LxO z9o}14HLR#3>)ginmt31*4STF!G~AyFYf?6UzCeo}rZ~DuBE+yjdFJ$HHE+BbIcteE zSIhMB$dv?>KXWVervxJnE=Nf;8C-S%@FfdNx@ReG&AiESFnA&YwS>{-#wPi#q95iE zX3(#G?%1PsM}okiF8wPb?uMfUb~)dZv*MM6lg7Y&m4Fl8U54l3+nOFqX;<@H;EOk2# zKZ4#Tgxs!Nt|bH;PA{B^RvC4iZO`{Kwv})D_9}0&gFXwKI>E}F5r9H8Wc7};Cg8^Q zAa*ytbc1!8a2+%#CLuJHSABRjWmk1In9*Yl&fZ`mZS9l40OmmsBWz^xdvSsVlBL5( z(z3bWNrfF$rthCCb2+xh$Ypv^+kw@~;|cPidc1a=8Q29gsHsx6JsirwtTO3wzf7pz zrD2-KtyKW*3oV$a7IcenlT@AzL9^!tww cJN6D`$xpcK{293iRUlKot^P;Bt%ra9519+{AOHXW diff --git a/assets/eip-3005/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png b/assets/eip-3005/on-chain_vs_M-to-M_vs_M-to-1_gas-cost-structure.png deleted file mode 100644 index 1849b39b085e56c1a20dc168735d453c77d4272e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44630 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 jA=t7tEc&zWxK|@PFyp08~OPeL0P&@c> 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 vAy8B2;Qw4LZ-fFY Date: Mon, 28 Sep 2020 19:06:17 +0200 Subject: [PATCH 5/6] additional EIP changes based on Micah's feedback --- EIPS/eip-3005.md | 137 ++++++++++++++++++++++++++++++----------------- 1 file changed, 87 insertions(+), 50 deletions(-) diff --git a/EIPS/eip-3005.md b/EIPS/eip-3005.md index cb65e793a8c08..b05b266d99826 100644 --- a/EIPS/eip-3005.md +++ b/EIPS/eip-3005.md @@ -7,45 +7,76 @@ status: Draft type: Standards Track category: ERC created: 2020-09-25 -requires: 20 --- ## Simple Summary -A meta transaction is a cryptographically signed message that a user sends to a relayer who then makes an on-chain transaction based on the meta transaction data. A relayer effectively pays gas fees in Ether, while a meta tx sender can compensate the relayer in tokens (a "gas-less" transaction). +Defines an extension function for ERC-20 (and other fungible token standards), which allows receiving and processing a batch of meta transactions. -This proposal offers a solution to relay **multiple** meta transactions as a batch in one on-chain transaction. This reduces the gas cost that the relayer needs to pay, which in turn reduces the relayer fee that each meta tx sender pays in tokens. +![](../assets/eip-3005/meta-txs-directly-to-token-smart-contract.png) ## Abstract -The current meta transaction implementations (such as Gas Station Network - [EIP-1613](https://eips.ethereum.org/EIPS/eip-1613)) only relay one meta transaction through one on-chain transaction (1-to-1: 1 sender, 1 receiver). Gnosis Safe does the same, but can also relay a batch of meta transactions coming from **the same** sender (a 1-to-M batch: 1 sender, many receivers). +This EIP proposes a new function called `processMetaBatch()` that extends any fungible token standard, and enables batched meta transactions coming from many senders in one on-chain transaction. + +The function must be able to receive multiple meta transactions data and process it. This means validating the data and the signature, before proceeding with token transfers based on the data. -This EIP proposes a new function called `processMetaBatch()` (an extension to the ERC-20 token standard) that is able to process a **batch** of meta transactions arriving from **many** senders to **one or many** receivers (M-to-M or M-to-1) in one on-chain transaction. +The function enables senders to make gasless transactions, while reducing the relayer's gas cost due to batching. ## Motivation -Meta transactions have proven useful as a solution for Ethereum accounts that don't have any ether, but hold ERC-20 tokens and would like to move them (gas-less transactions). +Meta transactions have proven useful as a solution for Ethereum accounts that don't have any ether, but hold ERC-20 tokens and would like to transfer them (gasless transactions). -The current meta transaction relayer implementations only allow relaying one meta transaction at a time. +The current meta transaction relayer implementations only allow relaying one meta transaction at a time. Some also allow batched meta transactions from the same sender. But none offers batched meta transactions from **multiple** senders. -The motivation behind this EIP is to find a way to allow relaying multiple meta transactions (a batch) in one on-chain transaction, which also **reduces the total gas cost** that a relayer needs to cover. +The motivation behind this EIP is to find a way to allow relaying batched meta transactions from **many senders** in **one on-chain transaction**, which also **reduces the total gas cost** that a relayer needs to cover. ## Specification -### How the system works +### Meta transaction data -A user sends a meta transaction to a relayer (through relayer's web app, for example). The relayer waits for multiple meta txs to arrive until the meta tx fees (paid in tokens) cover the cost of the on-chain gas fee (plus some margin that the relayer wants to earn). +In order to successfully validate and transfer tokens, the proposed function needs to process the following data about a meta transaction: -Then the relayer relays a batch of meta transactions using one on-chain transaction to the token contract (triggering the `processMetaBatch()` function). +- sender address +- receiver address +- token amount +- relayer fee +- a (meta tx) nonce +- a timestamp or a block number (which represents a due date to process a meta tx) +- a token address +- a relayer address +- a signature -![](../assets/eip-3005/meta-txs-directly-to-token-smart-contract.png) +Not all of these data needs to be sent to the function by the relayer. Some of the data can be deduced or extracted from other sources (from transaction data and contract state). + +### Meta transaction nonce + +The token smart contract must keep track of a meta transaction nonce for each token holder. + +### Meta transaction validation + +Validation requirements: + +- sender and receiver addresses cannot be 0x0 +- timestamp or block number must not be expired +- the sender's balance be equal or greater than the sum of the token amount and the relayer fee +- all of the data described in *Meta transaction data* (except the signature) must be hashed. The signed hash must be validated in the function. + +### Token transfers + +If validation is successful, the meta nonce can be increased by 1 and the token transfers can occur: + +- The specified token amount goes to the receiver +- The relayer fee goes to the relayer (`msg.sender`) + +## Implementation -Technically, the implementation means **adding a couple of functions** to the existing **ERC-20** token standard: +The **reference implementation** adds a couple of functions to the existing ERC-20 token standard: - `processMetaBatch()` - `nonceOf()` -You can see the proof-of-concept implementation in this file: [ERC20MetaBatch.sol](https://github.com/defifuture/erc20-batched-meta-transactions/blob/master/contracts/ERC20MetaBatch.sol). This is an extended ERC-20 contract with added meta tx batch transfer capabilities (see function `processMetaBatch()`). +You can see the implementation of both functions in this file: [ERC20MetaBatch.sol](https://github.com/defifuture/erc20-batched-meta-transactions/blob/master/contracts/ERC20MetaBatch.sol). This is an extended ERC-20 contract with added meta transaction batch transfer capabilities. ### `processMetaBatch()` @@ -108,8 +139,6 @@ function processMetaBatch(address[] memory senders, } ``` -> Note that the OpenZeppelin ERC-20 implementation was used here. Some other implementation may have named the balances mapping differently, which would require minor changes in the `processMetaBatch()` function. - ### `nonceOf()` Nonces are needed due to the replay protection (see *Replay attacks* under *Security Considerations*). @@ -124,9 +153,9 @@ function nonceOf(address account) public view returns (uint256) { } ``` -> The EIP-2612 (`permit()` function) also requires a nonce mapping. At this point, I'm not sure yet if this mapping should be **re-used** in case a smart contract implements both EIP-3005 and EIP-2612. -> -> At the first glance, it seems the nonce mapping could be re-used, but this should be thought through (and tested) for possible security implications. +The link to the complete implementation (along with gas usage results) is here: [https://github.com/defifuture/erc20-batched-meta-transactions](https://github.com/defifuture/erc20-batched-meta-transactions). + +> Note that the OpenZeppelin ERC-20 implementation was used here. Some other implementation may have named the `_balances` mapping differently, which would require minor changes in the `processMetaBatch()` function. ## Rationale @@ -138,7 +167,7 @@ The `processMetaBatch()` function thus does the job of receiving a batch of meta ### Function parameters -As you can see, the `processMetaBatch()` function takes the following parameters: +As you can see, the `processMetaBatch()` function in the reference implementation takes the following parameters: - an array of **sender addresses** (meta txs senders, not relayers) - an array of **receiver addresses** @@ -147,36 +176,44 @@ As you can see, the `processMetaBatch()` function takes the following parameters - an array of **block numbers** (a due "date" for meta tx to be processed) - Three arrays that represent parts of a **signature** (v, r, s) -**Each item** in these arrays represents **data of one meta tx**. That's why the **correct order** in the arrays is very important. +**Each item** in these arrays represents **data of one meta transaction**. That's why the **correct order** in the arrays is very important. + +If a relayer gets the order wrong, the `processMetaBatch()` function would notice that (when validating a signature), because the hash of the meta transaction values would not match the signed hash. A meta transaction with an invalid signature is **skipped**. + +### The alternative way of passing meta transaction data into the function + +The reference implementation takes parameters as arrays. There's a separate array for each meta transaction data category (the ones that cannot be deduced or extracted from other sources). + +A different approach would be to bitpack all data of a meta transaction into one value and then unpack it within the smart contract. The data for a batch of meta transactions would be sent in an array, but there would need to be only one array (of packed data), instead of multiple arrays. -If a relayer gets the order wrong, the `processMetaBatch()` function would notice that (when validating a signature), because the hash of the meta tx values would not match the signed hash. A meta transaction with an invalid signature is **skipped**. +### Why is nonce not one of the parameters in the reference implementation? -### Why is nonce not one of the parameters? +Meta nonce is used for constructing a signed hash (see the `msgHash` line where a `keccak256` hash is constructed - you'll find a nonce there). -Meta nonce is used for constructing a signed hash (see the `msgHash` line where a `keccak256` hash is constructed - you'll find a nonce there). Since a new nonce has to always be bigger than the previous one by exactly 1, there's no need to include it as a parameter array in the `processMetaBatch()` function, because its value can be deduced. +Since a new nonce has to always be bigger than the previous one by exactly 1, there's no need to include it as a parameter array in the `processMetaBatch()` function, because its value can be deduced. This also helps avoid the "Stack too deep" error. +### Can EIP-2612 nonces mapping be re-used? + +The EIP-2612 (`permit()` function) also requires a nonce mapping. At this point, I'm not sure yet if this mapping should be **re-used** in case a smart contract implements both EIP-3005 and EIP-2612. + +At the first glance, it seems the `nonces` mapping from EIP-2612 could be re-used, but this should be thought through (and tested) for possible security implications. + ### Token transfers -Token transfers could alternatively be done by calling the `_transfer()` function (part of the OpenZeppelin ERC-20 implementation), but it would increase the gas usage and it would also revert the whole batch if some meta tx was invalid (the current implementation just skips it). +Token transfers in the reference implementation could alternatively be done by calling the `_transfer()` function (part of the OpenZeppelin ERC-20 implementation), but it would increase the gas usage and it would also revert the whole batch if some meta transaction was invalid (the current implementation just skips it). Another gas usage optimization is to assign total relayer fees to the relayer at the end of the function, and not with every token transfer inside the for loop (thus avoiding multiple SSTORE calls that cost 5'000 gas). ## Backwards Compatibility -The code implementation of batched meta transactions is backwards compatible with ERC-20 (it only extends it with one function). +The code implementation of batched meta transactions is backwards compatible with any fungible token standard, for example, ERC-20 (it only extends it with one function). ## Test Cases Link to tests: [https://github.com/defifuture/erc20-batched-meta-transactions/tree/master/test](https://github.com/defifuture/erc20-batched-meta-transactions/tree/master/test). -## Implementation - -Link to the implementation (along with gas usage results): [https://github.com/defifuture/erc20-batched-meta-transactions](https://github.com/defifuture/erc20-batched-meta-transactions). - -The `processMetaBatch()` function can be found in **contracts/ERC20MetaBatch.sol**. - ## Security Considerations Here is a list of potential security issues and how are they addressed in this implementation. @@ -191,21 +228,21 @@ The `processMetaBatch()` function then verifies the signature using `ecrecover() The `processMetaBatch()` function is secure against two types of a replay attack: -**Using the same meta tx twice in the same token smart contract** +**Using the same meta transaction twice in the same token smart contract** -A nonce prevents a replay attack where a relayer would send the same meta tx more than once. +A nonce prevents a replay attack where a relayer would send the same meta transaction more than once. -**Using the same meta tx twice in different token smart contracts** +**Using the same meta transaction twice in different token smart contracts** -A token smart contract address must be added into the signed hash (of a meta tx). +A token smart contract address must be added into the signed hash (of a meta transaction). -This address does not need to be sent as a parameter into the `processMetaBatch()` function. Instead the function uses `address(this)` when constructing a hash in order to verify the signature. This way a meta tx not intended for the token smart contract would be rejected (skipped). +This address does not need to be sent as a parameter into the `processMetaBatch()` function. Instead, the function uses `address(this)` when constructing a hash in order to verify the signature. This way a meta transaction not intended for the token smart contract would be rejected (skipped). ### Signature validation Signing a meta transaction and validating the signature is crucial for this whole scheme to work. -The `processMetaBatch()` function validates a meta tx signature, and if it's **invalid**, the meta tx is **skipped** (but the whole on-chain transaction is **not reverted**). +The `processMetaBatch()` function validates a meta transaction signature, and if it's **invalid**, the meta transaction is **skipped** (but the whole on-chain transaction is **not reverted**). ```solidity msgHash = keccak256(abi.encode(sender, recipients[i], amounts[i], relayerFees[i], newNonce, blocks[i], address(this), msg.sender)); @@ -215,15 +252,15 @@ if(sender != ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\ } ``` -Why not reverting the whole on-chain transaction? Because there could be only one problematic meta tx, and the others should not be dropped just because of one rotten apple. +Why not reverting the whole on-chain transaction? Because there could be only one problematic meta transaction, and the others should not be dropped just because of one rotten apple. -That said, it is expected of relayers to validate meta txs in advance before relaying them. That's why relayers are not entitled to a relayer fee for an invalid meta tx. +That said, it is expected of relayers to validate meta transactions in advance before relaying them. That's why relayers are not entitled to a relayer fee for an invalid meta transaction. ### Malicious relayer forcing a user into over-spending A malicious relayer could delay sending some user's meta transaction until the user would decide to make the token transaction on-chain. -After that, the relayer would relay the delayed meta tx which would mean that the user would have made two token transactions (over-spending). +After that, the relayer would relay the delayed meta transaction which would mean that the user would have made two token transactions (over-spending). **Solution:** Each meta transaction should have an "expiry date". This is defined in a form of a block number by which the meta transaction must be relayed on-chain. @@ -249,7 +286,7 @@ function processMetaBatch(... A malicious relayer could scout the Ethereum mempool to steal meta transactions and front-run the original relayer. -**Solution:** The protection that `processMetaBatch()` function uses is that it requires the meta tx sender to add the relayer's Ethereum address as one of the values in the hash (which is then signed). +**Solution:** The protection that `processMetaBatch()` function uses is that it requires the meta transaction sender to add the relayer's Ethereum address as one of the values in the hash (which is then signed). When the `processMetaBatch()` function generates a hash it includes the `msg.sender` address in it: @@ -261,19 +298,19 @@ if(sender != ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\ } ``` -If the meta tx was "stolen", the signature check would fail because the `msg.sender` address would not be the same as the intended relayer's address. +If the meta transaction was "stolen", the signature check would fail because the `msg.sender` address would not be the same as the intended relayer's address. -### A malicious (or too impatient) user sending a meta tx with the same nonce through multiple relayers at once +### A malicious (or too impatient) user sending a meta transaction with the same nonce through multiple relayers at once -A user that is either malicious or just impatient could submit a meta tx with the same nonce (for the same token contract) to various relayers. Only one of them would get the relayer fee (the first one on-chain), while the others would get an invalid meta transaction. +A user that is either malicious or just impatient could submit a meta transaction with the same nonce (for the same token contract) to various relayers. Only one of them would get the relayer fee (the first one on-chain), while the others would get an invalid meta transaction. -**Solution:** Relayers could **share a list of their pending meta txs** between each other (sort of an info mempool). +**Solution:** Relayers could **share a list of their pending meta transactions** between each other (sort of an info mempool). The relayers don't have to fear that someone would steal their respective pending transactions, due to the front-running protection (see above). -If relayers see meta transactions from a certain sender address that have the same nonce and are supposed to be relayed to the same token smart contract, they can decide that only the first registered meta tx goes through and others are dropped (or in case meta txs were registered at the same time, the remaining meta tx could be randomly picked). +If relayers see meta transactions from a certain sender address that have the same nonce and are supposed to be relayed to the same token smart contract, they can decide that only the first registered meta transaction goes through and others are dropped (or in case meta transactions were registered at the same time, the remaining meta transaction could be randomly picked). -At a minimum, relayers need to share this meta tx data (in order to detect meta tx collision): +At a minimum, relayers need to share this meta transaction data (in order to detect meta transaction collision): - sender address - token address @@ -281,7 +318,7 @@ At a minimum, relayers need to share this meta tx data (in order to detect meta ### Too big due block number -The relayer could trick the meta tx sender into adding too big due block number - this means a block by which the meta tx must be processed. The block number could be far in the future, for example, 10 years in the future. This means that the relayer would have 10 years to submit the meta transaction. +The relayer could trick the meta transaction sender into adding too big due block number - this means a block by which the meta transaction must be processed. The block number could be far in the future, for example, 10 years in the future. This means that the relayer would have 10 years to submit the meta transaction. **One way** to solve this problem is by adding an upper bound constraint for a block number within the smart contract. For example, we could say that the specified due block number must not be bigger than 100'000 blocks from the current one (this is around 17 days in the future if we assume 15 seconds block time). @@ -296,7 +333,7 @@ if(block.number > blocks[i] || blocks[i] > (block.number + 100000)) { This addition could open new security implications, that's why it is left out of this proof-of-concept. But anyone who wishes to implement it should know about this potential constraint, too. -**The other way** is to keep the `processMetaBatch()` function as it is and rather check for the too big due block number **on the relayer level**. In this case, the user could be notified about the problem and could issue a new meta tx with another relayer that would have a much lower block parameter (and the same nonce). +**The other way** is to keep the `processMetaBatch()` function as it is and rather check for the too big due block number **on the relayer level**. In this case, the user could be notified about the problem and could issue a new meta transaction with another relayer that would have a much lower block parameter (and the same nonce). ## Copyright From 5f8d78dd0c268bc1e1658a2fb15a52abfcc94ea5 Mon Sep 17 00:00:00 2001 From: defifuture <67232250+defifuture@users.noreply.github.com> Date: Tue, 29 Sep 2020 13:38:08 +0200 Subject: [PATCH 6/6] the trailing space removed from the discussion link; a few wording changes --- EIPS/eip-3005.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/EIPS/eip-3005.md b/EIPS/eip-3005.md index b05b266d99826..5391fba9ebd9f 100644 --- a/EIPS/eip-3005.md +++ b/EIPS/eip-3005.md @@ -2,7 +2,7 @@ eip: 3005 title: Batched meta transactions author: Matt (@defifuture) -discussions-to: https://ethereum-magicians.org/t/eip-3005-the-economic-viability-of-batched-meta-transactions/4673 +discussions-to: https://ethereum-magicians.org/t/eip-3005-the-economic-viability-of-batched-meta-transactions/4673 status: Draft type: Standards Track category: ERC @@ -13,11 +13,9 @@ created: 2020-09-25 Defines an extension function for ERC-20 (and other fungible token standards), which allows receiving and processing a batch of meta transactions. -![](../assets/eip-3005/meta-txs-directly-to-token-smart-contract.png) - ## Abstract -This EIP proposes a new function called `processMetaBatch()` that extends any fungible token standard, and enables batched meta transactions coming from many senders in one on-chain transaction. +This EIP defines a new function called `processMetaBatch()` that extends any fungible token standard, and enables batched meta transactions coming from many senders in one on-chain transaction. The function must be able to receive multiple meta transactions data and process it. This means validating the data and the signature, before proceeding with token transfers based on the data. @@ -31,11 +29,13 @@ The current meta transaction relayer implementations only allow relaying one met The motivation behind this EIP is to find a way to allow relaying batched meta transactions from **many senders** in **one on-chain transaction**, which also **reduces the total gas cost** that a relayer needs to cover. +![](../assets/eip-3005/meta-txs-directly-to-token-smart-contract.png) + ## Specification ### Meta transaction data -In order to successfully validate and transfer tokens, the proposed function needs to process the following data about a meta transaction: +In order to successfully validate and transfer tokens, the `processMetaBatch()` function needs to process the following data about a meta transaction: - sender address - receiver address @@ -47,7 +47,7 @@ In order to successfully validate and transfer tokens, the proposed function nee - a relayer address - a signature -Not all of these data needs to be sent to the function by the relayer. Some of the data can be deduced or extracted from other sources (from transaction data and contract state). +Not all of the data needs to be sent to the function by the relayer. Some of the data can be deduced or extracted from other sources (from transaction data and contract state). ### Meta transaction nonce