Do not pay transaction fees in Ethereum

Anton Bukov
BitClave
Published in
2 min readApr 26, 2018

Warning: read this article and be aware of ERC827 usage, it is under discussion right now: https://github.com/ethereum/EIPs/issues/827

We at BitClave recently developed a way not to pay transaction fees in Ethereum for this case: in our system some of users have only CAT tokens on their accounts/wallets (have no ETH). So transferring these tokens were impossible until accounts were funded with ether. But what if we want to allow users to pay fees in CAT tokens? Sounds crazy? Let’s dive in.

We developed a trustless and secure way to allow anyone to pay fees for anyone without anyone being able to steal funds. For example Alice will be able to create some kind of token transfer transaction, send this transaction to Bob, and Bob will be able to perform this transaction in Ethereum network and pay fees for it. So you are able to create a service working with your own token and using no ETH, it will pay all transaction fees for users and compensate with the tokens.

We are glad to intoduce you to our simple library allowing transaction delegation in your inherited smart contracts easily: https://github.com/bitclave/Feeless

  1. Inherit your smart contract from Feeless smart contract
  2. Add feeless modifier for any methods you want to allow to call indirectly
  3. Use msgSender instead of msg.sender in these methods and methods internally called by them

An example of a ERC20 token smart contract, that allows to delegate transfers:

contract MyToken is StandardToken, Feeless {    string public constant symbol = “XXX”;
string public constant name = “MyToken”;
uint8 public constant decimals = 18;
string public constant version = “1.0”;
function transfer(address _to, uint256 _value)
public
feeless
returns(bool)
{
balances[msgSender] = balances[msgSender].sub(_value);
balances[_to] = balances[_to].add(_value);
Transfer(msgSender, _to, _value);
return true;
}
}

Now every holder can create signed agreement for the transactions:

const target = myToken.options.address;const nonce = await myToken.methods.nonces(wallet1).call();const data = await myToken.methods.transfer(wallet2, 5 * 10**18).encodeABI();const hash = web3.utils.sha3(target + data.substr(2) + web3.utils.toBN(nonce).toString(16,64));const sig = await web3.eth.accounts.sign(hash, wallet1PrivateKey);

And send target, data, nonce and sig to anyone who will be resposible for fees payment:

await myToken.performFeelessTransaction(
wallet1, target, data, nonce, sig
).send({ from: wallet2 });

You still do not need to trust anyone in this scheme. Also you can add transferWithFee method to pay fees with tokens to transaction executor:

function transferWithFee(address _to, uint256 _value, uint256 _fee)
public
feeless
returns(bool)
{
balances[msgSender] = balances[msgSender].sub(_value);
balances[_to] = balances[_to].add(_value);
Transfer(msgSender, _to, _value);
balances[msgSender] = balances[msgSender].sub(_fee);
balances[msg.sender] = balances[msg.sender].add(_fee);
Transfer(msgSender, msg.sender, _fee);
return true;
}

Can’t wait to get some feedback from the community.

--

--