ERC865: A case for more user-friendly tokens

This standard proposes a system to abstract away the gas and provides an ability for token holders to pay the transaction fee for *token transfer* in tokens instead of gas, in a single transaction.

Fee in ethereum:

To perform any transaction on ethereum blockchain, you have to pay a fee. This fee is paid to the miners for mining transactions, putting them into blocks, and securing the blockchain.
This fee is calculated in Gas(Gas Limit * Gas Price) and is paid in ether.

This creates some friction for new users:
1. New users have to understand how ethereum works in order to understand the gas price and gas cost
2. They have to acquire the necessary ether to pay for the gas

These two create unnecessary hurdles for the adoption of DAPPS with inbuilt tokens. This process should be abstracted away for simplicity so that users can use the DAPP without being concerned about underlying ethereum network

ERC865 is a novel step in this direction to address these issues and provide a better UX for ERC20 token transfers.w

ERC865:
This standard proposes a system to abstract away the gas and provides an ability for token holders to pay the transaction fee for *token transfer* in tokens instead of gas, in a single transaction.

A intermediary third party is introduced who is willing to take transfer fee in tokens and forward the transfer transaction with necessary fee in ether to the blockchain. This process is secured using cryptographic signatures.

Specifications:

  • A: Sender of the payment
  • B: Recipient of the payment
  • D: Delegate, doing the transaction for A, and paying for the gas
  • X: Amount of Token T sent from A to B
  • Y: Fee paid in Token T, from A to D for the transaction
  • T: Token to send
  • N: Nonce
  • S: Signed message from sender containing all the details of the transaction

Process:

  1. The user A chooses a quote from the delegate D for the value of the fee Y for 1 transaction (depending on gas price + value of token in ETH).
  2. With their private key, the user generates S by taking the sha3 of the payload P{T, B,X, Y, N}and signing it using the private key.
  3. The user sends P(unhashed, unsigned) to the delegate and S
  4. The delegate verifies that Y and D have not been altered
  5. The delegate proceeds to submit the transaction from his account D
    T.delegatedTransfer(S, B, X, Y, N)
  6. The delegatedTransfer method reconstructs the sha3 H of the payload P
  7. We can then call ecrecover(S) and, make sure that the result matches A, and if that’s the case, safely move X tokens from A to B and Y tokens from A to D.

TECHNICALS:
function delegatedTransfer(
 bytes _signature,
 address _to,
 uint256 _value,
 uint256 _fee,
 uint256 _nonce
) public returns (bool)

Is called by the delegate, and performs the transfer.

reference implementation of delegatedTransfer:
function delegatedTransfer(
 bytes _signature,
 address _to,
 uint256 _value,
 uint256 _fee,
 uint256 _nonce
 ) public returns (bool) {
 require(_to != address(0));
 require(signatures[_signature] == false);
 bytes32 hashedTx = transferPreSignedHashing(address(this), _to, _value, _fee, _nonce);
 address from = ecrecover(hashedTx, _signature);
 require(from != address(0));
 balances[from] = balances[from].sub(_value).sub(_fee);
 balances[_to] = balances[_to].add(_value);
 balances[msg.sender] = balances[msg.sender].add(_fee);
 signatures[_signature] = true;
 Transfer(from, _to, _value);
 Transfer(from, msg.sender, _fee);
 TransferPreSigned(from, _to, msg.sender, _value, _fee);
 return true;
}

function transferPreSignedHashing(
 address _token,
 address _to,
 uint256 _value,
 uint256 _fee,
 uint256 _nonce
 ) public pure returns (bytes32)
 {
 /* “48664c16”: transferPreSignedHashing(address,address,address,uint256,uint256,uint256) */
 return keccak256(bytes4(0x48664c16), _token, _to, _value, _fee, _nonce);
 }

Suggestions:
1. There should be a mechanism to invalidate a transaction.
2. There should be a time bound optional condition in the transaction so that the transaction becomes invalid after specified point of time. This makes revoking transaction automatic after the timeout ,and gives a cancellation mechanism without sending an explicit invalidating transaction

This standard is an ongoing WIP and can be found here:
1. https://github.com/ethereum/EIPs/issues/865
2. Reference implementation