Understanding Ethereum Meta Transaction

Andrea f Speziale
5 min readJul 8, 2019

What I really like about Ethereum
are the endless challenges around it.

As a lot of great developers from all over the world are pushing hard to make Ethereum 2.0 real, the fight to make it mainstream is still ongoing and it is a 🌶 topic.

Lately I’ve been studying meta transactions wondering if ether-less accounts can interact with the blockchain and possibly pay for GAS in ERC20 tokens.

The starting point for my research is the contribution of the amazing Austin Griffith who I met during ETHCC19 and I’m writing this article to help newbies like me find a simple way to approach what meta transactions are.

In my perception meta transactions aren’t just a creative way of improving Ethereum on-boarding. More in general they are a way of agreeing on something and make it happen.

The bouncer proxy approach

The bouncer proxy approach consists in four elements:

  • The user account: A private/public key pair which doesn’t own any ETH. The account can sign messages which can be EVM instructions;
  • The miner account: A private/public key pair owning ETH and available for paying the blockchain transaction fee on behalf of a user;
  • The bouncer proxy smart contract: The smart contract which takes as input a signed message submitted by a third party;
  • The recipient smart contract: It is the smart contract which the user would like to interact with.

In a scenario where:

  • A user has one or more Ethereum accounts which don’t have any ETH and don’t want to expose;
  • The user is the owner of a proxy contract which can forward calls only if the input message is signed by the user itself or its whitelisted accounts;
  • The proxy contract is funded with assets like ETH or ERC20s which can be used to reward miners based on the users instructions.

In order to submit a transaction to the Ethereum network — without paying any GAS — a user account should begin with creating, hashing and signing a message.

The hashed signed message is the user meta transaction representing a transaction with some decorators and it is composed by:

  • The proxy smart contract address;
  • The user address;
  • The transaction smart contract recipient;
  • The user transaction object value field;
  • The user transaction object data field;
  • The address of the asset to be used as reward for the current meta transaction;
  • The amount of the asset to be used as reward for the current meta transaction;
  • The user proxy contract nonce.

If you are reading this article, you are probably familiar with most of the parameters listed above. On the other hand you may find what I call the user proxy contract nonce rather confusing due to the shared purpose of the more general Ethereum account nonce. Both keep track of the number of the transactions made by an account preventing replay attacks and preserving the transactions order. The user proxy contract nonce is only limited to the executions made through the proxy contract.
As a matter of fact the proxy contract nonce is connected to the user, stored in a state variable in the proxy smart contract and updated every time a new meta transaction is processed by the smart contract.

When the meta transaction is ready, a miner account takes it up and invokes the forward function of the proxy contract.

The forward function inputs are:

  • The hashed signed message created by the user account;
  • The address of the user account which is the signer;
  • The transaction smart contract recipient;
  • The user transaction object value field;
  • The user transaction object data field;
  • The address of the asset to be used as reward for the current meta transaction;
  • The amount of the asset to be used as reward for the current meta transaction.

The smart contract generates the hashed message using the function parameters, as follows:

and validates the signer identity. This implies that only a meta transaction signed by the user or a whitelisted account can be proxied and a miner can be rewarded.

When the signer is validated, the reward amount is transferred from the proxy contract to the miner account.

The proxy executes the meta transaction instruction invoking the executeCall function and the miner account is paying the GAS for it.

At this point we have an ether-less user account which achieved the submission of its transaction potentially paying for GAS in ERC20 tokens.

You can give it a try cloning this Github repository.

It feels like magic

but you’ll get wasted along the road

because the proxy approach may be a pain in the a**:

  • Each user should be able to deploy its own proxy SC;
  • The reward assets must be owned by the proxy SC;
  • Each user should be able to manage and fund its own proxy SC.

In addition, if the business logic of your meta transaction smart contract recipient is based on the msg.sender identity, the interaction with it won’t be smooth.

Let’s pretend a user with no ETH tries to invoke an ERC20 approve method through a proxy smart contract to allow another trusted user to move its funds.

Inspired https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/token/ERC20/ERC20.sol

The user prepares the meta transaction, a miner submits it to the proxy smart contract and the contract executes it. As a result the trusted user can move funds from the proxy contract rather than from the user.

This issue can be addressed using the native meta transactions.

The native meta transactions approach

In the native meta transaction approach the meta transaction signer is retrieved in the meta transaction recipient rather than the proxy smart contract.

An ether-less account can approve another trusted account creating a meta transaction and the miner invokes the metaApprove method rather than the standard ERC20 approve method.

Inspired https://github.com/austintgriffith/native-meta-transactions/blob/master/contracts/MetaCoin/MetaCoin.sol

The signer address, as in the bouncer proxy approach, is retrieved from the signature parameter and it is delivered to the _approve function without resorting the msg.sender.

As a result the trusted user account is now able to move ERC20 funds on behalf of the user.

Unfortunately this approach can’t be applied to ERC20 tokens which were already deployed because they don’t support meta transactions.

Now what?

My teammates and I feel that the hack could be done by mixing ingredients together — (buzzword alert) “back-end”, “smart contracts”, “atomic swaps” and “event listeners” — and then share the recipe with the community.

If you liked this post, it would be amazing if you’d hit the Recommend button below, which will mean more people see it. You can also find me over on Twitter. Thanks!

--

--

Andrea f Speziale

Occasional writer and impostor coder. Randomly traversing the software engineering black hole 🕳️ #typescript and #nodejs enthusiast @Musixmatch