Suppose there exists Fancycoin, an ERC20 altcoin which has some functionality implemented by the EVM. It does some nontrivial things that take up gas.

According to my understanding, I can receive Fancycoin in my wallet if somebody sends it to me, without having any ether myself.

My question is: if I have Fancycoin and I want to use it to do something (maybe it checks an oracle, or does compututations with some data internal to a block, etc.) but I don't have any ether in my wallet, will I be unable to use any of the features of Fancycoin? As mentioned in the answer to the question linked within the first comment below, I probably will not be able to send Fancycoin to someone else.) However, could functions in Fancycoin requiring gas be paid in Fancycoin somehow, and not ether?

Answering the above counts as an answer to my question, but in case you want to expand: I think most generally I'm interested in how coins built on top of Ethereum interact with ether. I don't understand this.


The default answer would be: No, you cannot use an account without Ether for anything related to the Fancycoin, as any interaction with a standard token requires a transaction which you need to sign and broadcast to the network and conversely pay for the transaction costs in Ether (at least for the time being you can only pay fees in Ether).

The more interesting answer is: Yes, by changing the requirements somewhat. You do sign a transaction off-chain, send it to someone else (e.g. by means of a pigeon, snail mail, or smoke signals). That someone else might then be able to send that transaction and potentially get a little reward for doing so.

The above idea is not all ironed (indicated security issues remain) but the following sketch works, I just tested it in Remix with a little help of the geth web3 console:

pragma solidity ^0.4.13;

Author: Dr. Sebastian C. Buergel for Validity Labs AG
License: MIT

allow account without ETH but in possession of tokens to transfer tokens

sign message off-chain, send to other user, incentivize that user to broadcast message and get token as reward

remaining issues and solutions:
- replay protection (use nonce),
- frontrunning by other nodes (commit-reveal),
- timeout (expiry time)

step 0: choose amount, recipient (to), and reward (in tokens) for broadcaster
step 1: obtain hash from `calcHash` (off-chain, offline)
step 2: sign hash (off-chain, offline), e.g. using geth web3 console:
var signature = web3.eth.sign(web3.eth.accounts[0], hash);
var r = signature.substring(0,66);
var s = '0x' + signature.substring(66,130);
var v = '0x' + signature.substring(130,132); // make sure it is 27 or 28, else add 27

step 3: send transaction to someone else
step 4: that other account broadcasts the message by sending it to `broadcast`, funds get transferred and broadcaster gets reward

contract Fancycoin {

    event Transfer(address indexed _from, address indexed _to, uint256 _value);

    mapping(address => uint) public balanceOf;

    uint public totalSupply;

    constructor(uint supply) {
        totalSupply = supply;
        balanceOf[msg.sender] = supply;

    function transfer(address _to, uint256 _value) returns (bool success) {
        return transferFromTo(msg.sender, _to, _value);

    function transferFromTo(address _from, address _to, uint _value) internal returns (bool success) {
        if (balanceOf[_from] >= _value && _value > 0) {
            balanceOf[_from] -= _value;
            balanceOf[_to] += _value;
            Transfer(_from, _to, _value);
            return true;
        } else { return false; }

    // helper function since web3.sha3 is not (yet) able to concatenate arguments in the same way that solidity does it
    function calcHash(uint amount, address to, uint reward) constant returns (bytes32) {
        return sha3(amount, to, reward);

    function verify(uint amount, address to, uint reward, uint8 v, bytes32 r, bytes32 s) constant returns(address) {
        bytes memory prefix = "\x19Ethereum Signed Message:\n32";
        bytes32 prefixedHash = sha3(prefix, sha3(amount, to, reward));
        return ecrecover(prefixedHash, v, r, s);

    function broadcast(uint amount, address to, uint reward, uint8 v, bytes32 r, bytes32 s) {
        address sender = verify(amount, to, reward, v, r, s);
        assert(transferFromTo(sender, msg.sender, reward));
        assert(transferFromTo(sender, to, amount));

  • Looks great, just suggestion to move the [27,28] signature comment from r value to v value line. – GViz Jun 21 '19 at 18:06
  • thanks @GViz, fixed! – SCBuergel.eth Jun 23 '19 at 7:07
  • revisiting this now, a couple of things. less critically, web3.utils.soliditySha3(param1 [, param2, ...]) will concatenate and calcHash is generally unnecessary. There are utility contracts extant on the chain or just implement locally. More importantly, the broadcast design can drain funds for the broadcaster due to the assert steps, so this would be safer if a read only call was made to test before sending to the network. – GViz Mar 21 '20 at 18:37

Just answered and provided a link to the universal library, allowing easily integrate this functionality into any smart contract: https://ethereum.stackexchange.com/a/46546/3032

Anyone will be able to perform transactions for anyone in a trustless and secure way. For example, service can perform transaction for it users (with their digital signatures per transactions) and compensate ETH fees with own token fees.


I've actually got an example of a master contract (that must store ether) that can create child wallets that don't individually need to hold ether themselves!

Please star it if you you like it: https://github.com/Meshugah/ERC20-CommonGasWallet

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.