/ research

Relayed Transactions: Our Proposal For User-Friendlier Ethereum Tokens

In June 2015, Ethereum's Vitalik Buterin introduced EIP20, also known as the ERC20 token standard. Buterin's proposal paved the way for an entirely new generation of cryptocurrencies more commonly known as Ethereum tokens. Today, thanks to the ease of launching custom new tokens -unlike native coins- in only a matter of minutes, ERC20 adoption has grown exponentially, making them Ethereum smart contracts' top use case.

Despite this, ERC20-compliant tokens come with a big disadvantage against native coins: They require every user to possess a small amount of Ether in order to cover the smart contract gas fees. In the early days, tokens were mostly held by the existing crypto community, so this wasn't much of a problem to those already familiar with Ether and gas. But today, many Ethereum developers seek to create highly competitive decentralized applications that are capable of disrupting existing centralized services. And in order to reach widespread adoption, these applications require the best possible user experience. An experience where, for instance, users are only expected to acquire and hold a token that is relevant to the application they are using. Ideally, users must (A) never tell the difference between an application that uses tokens managed by an Ethereum smart contract and one that uses tokens managed by a central database and (B) not be required to understand blockchain-specific concepts such as gas fees.

Existing solutions

Among others, Swarm City proposed a solution to this problem by introducing the Gas Station Service. Without going too much into details, users were required to take action in order to exchange their ERC20 token for Ether every time they run out of gas. While their approach did allow users not to buy Ether in order to pay for gas fees, it did not fulfill condition (B) mentioned above. This resulted in further deteriorating the user experience instead of improving it.
We believe that no one has introduced a definitive solution to this problem so far due to the limitations of the ERC20 standard itself. Thus, it must be replaced.

Relayed Transactions Standard

We propose a complementary standard to the ERC20 standard.
In our approach, instead of interacting with a Solidity smart contract directly, a user broadcasts a signed message containing the transaction arguments (in the case below, _from, _to and _value) across an off-chain pool of relay nodes. Within a timeout (_timeout) defined by the signer, the first relay to (A) pick up the message, (B) sign it using his own private key in the form of a transaction, (C) relay it to the smart contract and (D) pay the gas fees in Ether on behalf of the signer, is rewarded with the pre-defined fee (_fee) deducted from the signer's token balance.

In order to implement relayed transactions in any Solidity function, the following arguments must be defined:

  • _fee: a fee in tokens pre-defined by the message signer
  • _timeout: a unix timestamp timeout pre-defined by the message signer
  • v, r, s: the original sender's signature

Here's a code sample of a relayed token transfer function written in Solidity:

mapping (bytes32 => bool) public relayed;
       
function relayTransfer(address _from, address _to, uint256 _value, uint256 _fee, uint256 _timeout, uint8 v, bytes32 r, bytes32 s) public {
    require(balances[_from] >= (_value + _fee) && now < _timeout);
    bytes32 hash = keccak256(_from, _to, _value, _fee, _timeout);
    require(relayed[hash] != true);
    require(ecrecover(hash, v, r, s) == _from);
    balances[_from] -= (_value + _fee);
    balances[_to] += _value;
    balances[msg.sender] += _fee;
    Transfer(_from, _to, _value);
    Transfer(_from, msg.sender, _fee);
    relayed[hash] = true;
}

Here's what's happening in the code above:

  • The smart contract concatenates the provided arguments _from, _to, _value, _fee and _timeout and produces the hash of the concatenated value.
  • The smart contract checks a mapping to ensure that the same hash was not previously produced and stored in order to prevent replay attacks.
  • The smart contract verifies that the provided signature (v, r, s) matches the produced hash and is signed by the original sender _from.
  • The smart contract transfers the _value amount of tokens from the _from address to the _to address and the _fee amount of tokens to the relay (msg.sender)
  • The smart contract emits a Transfer() event for the _value amount and another for the _fee amount.
  • Finally, the smart contract stores the hash in a mapping in order to prevent future replays

Backward Compatibility

Since our proposed standard is a complementary standard and assumes that a smart contract is also ERC20-compliant as a prerequisite, this leaves an option to users who do hold Ether to use ERC20 functions such as transfer() in order to interact with the smart contract directly and pay fees in Ether.

While we applied the proposed standard to a function equivalent to the transfer() function, it could also be implemented to any other Solidity function that lives on an ERC20-compliant contract. This said, we do not recommend implementing relayed transactions on call function names reserved by the ERC20 standard such as transfer(), transferFrom() or approve() (notice the function in the code above is named relayTransfer()). Otherwise, this will break compatibility with ERC20-compliant wallets.

Implementation

We are currently working on the first implementation of the proposed standard in Dcourt's upcoming smart contract in order to enhance user experience. We will update this section once the implementation is publicly released.

ERC Ethereum Improvement Proposal

Since the EIP1 mandates the "vetting of an idea publicly before going as far as writing an EIP", we wrote this blog post to initiate a discussion around our approach within the Ethereum community before filing an EIP draft in a more formalized language.

Feedback

This proposal is still in its very early days. We welcome feedback, improvement proposals and criticism. Feel free to contact me directly at nour@lamarkaz.com