Ethereum Meta Transactions : Our Take

Marcel
Bloxis
Published in
10 min readJan 16, 2020

This article is Bloxis’s response to the Generalised MetaTransaction Contest being run on Gitcoin by Metamask. We are heavily vested in this space due to the features we are planning to integrate into our upcoming product, and really wanted to be a part of the conversation! If you have any arguments against my points, please bring them up, would love the discussion.

Image Source : Gitcoin

Introduction

An Ethereum transaction can execute literally anything, within a (gas) limit, if you’re willing to pay for it — on what is hopefully a completely decentralised international blockchain network. This sounds really cool and it is. The problem, however, is the paying part! Transactions cost gas, gas is paid for in Ether, who the f*** has Eth?? (in the normal, non cypherpunk / HODLer / crypto trader MLM[smh], civilised world)

Image Source : DEEP FRIED THIS MEME MYSELF

The future of the DeFi, blockchain gaming and dApp ecosystems depend on normies entering the scene. This means fixing the onboarding problem, and reducing the amount of knowledge needed by users to safely interact on chain. Needing a wallet and need Eth are the main two issues — this is what a large part of the industry are trying to address.

Meta transactions are a type of transaction which is signed by a given key pair, but is funded by a “relay”. The relay submits the transaction to the network as if they are the sender, and pay the gas fee. The destination contract of the transaction can determine the original user, their intent and can process the contract call accordingly.

Before meta transactions existed, services relied on a pre-funding approach, where Ether would be deposited into the end user’s account to facilitate a transaction. An example of this is Uport’s Lambda Sensui.

A more indepth introduction can be read in the article below, by Austin Griffith — huge role model for the community

Implementations

On chain, meta transactions rely on a standard for encoding transaction data from the original sender — in a such a way that their signature and data can be recovered by the target contract, regardless of the msg.sender. Off chain, however, there must be APIs or messaging protocols to link the end user to their relay. The relay must also have the Ether and the infrastructure to take that meta transaction and forward it.

Niche use case solutions, such as the permit() method in Dai’s ERC-20 token contract, handle the on chain aspect in an elegant way — an approve method which does need the end user to submit directly. In addition, this method implements EIP-712, a standard for representing and signing message data intended for on-chain use. Arguably, this is the only meta transaction Dai needs to support, as all other use cases, such as sending Dai and orchestrating DeFi operations, can be made possible through solutions leveraging this.

The Gas Station Network goes a step further and creates a smart contract based network for regulating relays and also contract methods that enable any smart contract to support the network with minimal rework. All relays interact with contracts via a relay hub, a contract which also maintains a registry of relays for users. Contracts pay Ether to the relay hub to incentivise paying others gas, relays only get the funds when they successfully relay a transaction.

Contract Wallets

Many organisations such as Dapper Labs, Gnosis and Argent are putting contract wallets forward as a solution for UX and security. A contract wallet puts the users assets in the custody of a smart contract, where the functionality for sending transactions and securing accounts can be extended well beyond the specifications of the Ethereum protocol.

Co-signing features integrated into contract wallets enable an end user to indicate their intention to do a transaction by signing transactions with an key on their device, transmit this to a co-signer or forwarding party (usually the wallet service provider) who transmits the transaction and absorbs the gas cost. We can see this, for example, with Dapper Labs, with their invokeN…() method calls on their CoreWallet.

Image Source : Dapper Labs

This approach enables transactions which do not require the account owner to hold eth and don’t require the entire industry to adopt a standard — the contract wallets make calls to other contracts which are identical to externally owned accounts (standard keypairs, EOAs). In addition, it enables a range of security features, for example Authereum’s Transaction Firewall.

Image Source : Authereum

Our Concerns with Contract Wallets

The Ethereum community is very supportive of contract wallets, and other initiatives such as the Ethereum Name Service (ENS). With many users adopting the ENS address insertName.eth as the identity for their all on chain activity. With this, huge privacy and security concerns arise!

The ecosystem is simultaneously investing in zero knowledge privacy protocols such as AZTEC, which are dependent on the ownership and management of private keys, believing this to be the way forward — whilst simultaneously downplaying the importance of users handling key management and traditional privacy solutions.

“downplaying the importance of users handling key management and traditional privacy solutions”

Instead of supporting privacy through pseudo-anonymity, many wallet providers are encouraging their users to get ENS addresses, without having them understand the consequences. Namely, that accounts are public on chain, including their portfolio and dApps interacted with, in a way which can be profiled — and with ENS, that activity can be now be linked with a name. That name is a name most likely to be already used by the person, either on another service, or in real life. This is the main reason I am skeptical of ENS and contract wallets, for personal use.

However, I am very supportive of ENS being used to identify smart contracts to prevent scams and contract wallets / multisig being used by organisations which can benefit from being transparently operated.

Hierarchical Deterministic Wallets enable users to produce many different assets from a single private key, allowing them to maintain some level of anonymity even when transacting extensively with a large range of assets, dApps and DeFi protocols. With a HD wallet system, it is arguably possible to create an EOA address for every token and dApp a given user interacts with. This is also possible with contract wallets, but to create a wallet contract for every dApp/token a user uses would be highly prohibitive due to gas cost. Regardless of gas cost, it would congest the network.

Hierarchical Deterministic Wallets, a privacy solution in itself if applied to Ethereum wallets. Image Source : Casa

Hypothetically, if the Ethereum ecosystem was such that all users had a contract wallet for each dApp they interacted with, just to leverage meta-transaction features, whilst maintaining privacy aspect — it would be more logical for smart contracts to adopt a universal standard.

Moving towards a Generalised Standard

Regardless of your stance on the contract vs contract wallet based approach, there is yet to be a standard put in place — method calls vary from contract to contract, as do the systems for relaying the transaction. The Gas Station Network has done a lot of the ground work, however, it lacks flexibility. The recipient contract may not be in the entity that should pay the fee. How could the user remunerate the relay using their assets? How could we get another party to fund the transaction? These are problems we’d hope to solve in the Generalised MetaTransaction Contest — if we can whip up a worthy proposal.

Our General Legal Counsel, Vincent, whipped up this article on an idea we came up with to enable dApp developers to pre-fund users gas, in exchange for fiat, without it being considered to be an exchange, under the principle that the Ether is only usable within the dApp. This is the kind of dynamic we’d like to be supported in a generalised meta transaction standard going forward. (This was a year ago when we were working on a different idea). This is technically supported by The Gas Station Network already, via a custom implementation of acceptRelayedCall().

In addition, could we lower the gas cost incurred by relays, by allowing them to batch transactions.

In a proposal, regardless of origin, we’d like to see the following things :

  • Mechanisms to support alternative relay reimbursement / payment methods.
  • Methods which are designed to run within smart contracts used for assets dApps and DeFi — as opposed to a contract wallet standard
  • Mechanisms to support transaction batching, either within the target contract, or within a contract designed to relay transactions

Overview of Our Proposal

As you can see, we are huge fans of the ideas brought forward by The Gas Station Network. The getSender() and getMessageData() provided by RelayRecipient give a unified to make an entire contract meta transaction compatible. However, these methods in their current form have two shortcomings — there is no phishing and replay protection.

Metamask interface for signing data using the signTypedData_v4 method. Image Source : Metamask

EIP-712 has implemented a good solution for preventing phishing, a domain separator. This object contains details about the contract the user is signing a transaction to be forwarded to — namely the address, but also the name of the dApp and version. This data is included in the signature, and can be shown in a very friendly way to the end user — along with all other Tx data. This prevents users from signing Txs that are used in a way not intended, e.g. by forwarding to the wrong contract — on purpose.

Contracts supporting EIP-712 are supposed to verify the domain separator matches themselves, and revert if not. This can be seen in the code below, from the Dai smart contract. We’d like EIP-712 integrated into getSender() and getMessageData(), to enable this check to happen for every method call — reverting the transaction if the signature is incorrect. Check the link below to view the function code. (Sorry, the formatting for inline code wasn’t working properly)

In addition, you can see MakerDAO have implemented replay protection themselves, with a nonce attribute — without this, the approved party could drain the users funds by replaying the transaction.

A given meta transaction is often part of a set of operations, which may depend on previous transactions. For example, in a proof of concept we built, we enabled users to deposit xDai into the Compound Protocol. Within the mainnet, this meant approving the cDai contract to access the users funds, and then calling the mint() method, to deposit funds in the lending protocol.

Assuming the user’s account is not a contract wallet, this would mean calling the approve()/permit() transaction, waiting for it to be mined and calling mint(). With a contract wallet, however, it would be possible to execute this with one call to a specially made contract method to batch these transactions.

A generalised meta transaction batch method that any user could leverage would be an important innovation. It would simplify a lot on chain activities, such as the example above, additionally, it would allow the user to have multiple, unrelated transactions signed and relayed simultaneously.

Nonces and replay protection should be handled like how MakerDAO have handled it with the permit() method. This enables a user to have multiple messages for unrelated contracts forwarded, without having to worry about the submission order within the network — for example, if the user is paying for something IRL with multiple assets.

However, there are cases where users may wish to send multiple meta transactions to a given contract. For example, bulk payroll payout from a single EOA with a single asset. A batched meta transaction system must take this into account, and ensure transaction order is preserved.

In addition, batched transactions would enable relays to integrate their fee into the transactions the user signs, in a way which can be customised through adding a transaction to the batch to transfer funds to the relay. This could be an ERC-20 transfer to the relay, or the user getting the target contract to pay.

Batch transaction support should be moved to the relay hub, sendRawTransaction() should be complemented by a sendRawTransactionSet() method, for sending multiple transactions from the same user. A sendRawTransactionSetPlural() method should also be made, so relays can minimise gas cost via batching transactions from multiple users.

Image Source : Tabookey

This could be done with minimal changes to the current flow of RelayHub, if a transaction set is being funded via a transaction in the set, the relay can set the gasPrice and fee arguments acceptRelayCall() to zero. Once a transaction has been derived from a set, it could be processed as standard. This process would be looped for all transactions in a set etc.

The real challenge is creating a standard to package transactions into sets, and unpacking and executing them — in a way where atomicity can be guaranteed. Without a guarantee of atomicity, a relayer could cheat a user by only transmitting the fee paying transaction, whilst ignoring the rest of the set. This would be the bulk of the work. I have no idea how to practically do this right now, but stay tuned for the next episode! Hopefully I can turn this all into a viable entry to the competition.

Summary

We feel contract wallets, while really useful, are a little overrated and could be potentially compromising on-chain privacy — through encouraging behaviours that make users easier to profile. This has a really strong impact on how we want to see generalised meta transactions implemented in the Ethereum ecosystem.

We want to augment The Gas Station Network to support EIP-712 and bulk transactions. This would mean modifying RelayHub and RelayRecipient. It would also mean creating a standard to sign sets of transactions which can be guaranteed to be executed atomically.

Stay tuned and please leave feedback — this is my first Medium article!

--

--