I have user's private key to sign a erc20-token transfer transaction in my DAPP. Now I want to send this transaction from different account so that 2nd account pay the gas fee. Is it possible through web3. Contract itself doesn't have any method to verify signature and call the transfer method, it has default transfer method. How can I achieve this?

  • 1
    It is not possible unless the token has support for that feature ethereum.stackexchange.com/questions/38479/… and see this question about meta-transactions ethereum.stackexchange.com/questions/67510/….
    – Ismael
    Commented Jun 11, 2020 at 20:13
  • Not straightforward to do, and normally not possible for classic EIP20 token, but in fact it is actually possible to do that with a wrapper contract, but it will cost much more gas to execute a single transaction. Anyway it is not so difficult to develop, I think you can find someone that already did that around on the web. Commented Jun 11, 2020 at 22:20
  • ERC20 standard have included allowance method, you can use that. With the 1st account you create one transaction to "allow" the 2nd account to manage tokens.. This way the 2nd account will be paying for the transactions and he will be able to manage the 1st account erc20 tokens. Commented Jun 12, 2020 at 4:49
  • @MiroslavNedelchev allowance returns the approved balance. to allow some one else it is approve method which requires gas fee as it is writing on blockchain Commented Jun 12, 2020 at 5:23
  • 1
    @murtzagondal Too busy now, but maybe during the weekend I can create an example. Just to elaborate a bit more: the approve way is a dead end imho. You should instead create a wrapper contract that can control user tokens based on signed users messages. It's something similar to a wallet for tokens. Commented Jun 12, 2020 at 9:06

1 Answer 1


Following the comments to your question, here is a working example (tested with web3.js v1.2.1):

async function run()
    const web3 = new Web3(YOUR_NODE_URL);
    const contract = new web3.eth.Contract(YOUR_CONTRACT_ABI, YOUR_CONTRACT_ADDR);
    const account1 = web3.eth.accounts.privateKeyToAccount(ACCOUNT1_PRIVATE_KEY);
    const account2 = web3.eth.accounts.privateKeyToAccount(ACCOUNT2_PRIVATE_KEY);
    const transaction1 = contract.methods.approve(account2.address, TOKEN_AMOUNT);
    const transaction2 = contract.methods.transferFrom(account1.address, DEST_ADDR, TOKEN_AMOUNT);
    const receipt1 = await send(web3, account1, transaction1);
    const receipt2 = await send(web3, account2, transaction2);

async function send(web3, account, transaction) {
    const options  = {
        to      : transaction._parent._address,
        data    : transaction.encodeABI(),
        gas     : await transaction.estimateGas({from: account.address}),
    const signed  = await web3.eth.accounts.signTransaction(options, account.privateKey);
    const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction);
    return receipt;


Note that the first account will still need to pay gas for executing approve, which is not much different than paying gas for executing transfer to begin with.

The purpose of this ERC20 scheme, is not to allow someone else to pay for your gas, but to allow someone else to transfer a certain amount of tokens on your behalf.

This is a typical scenario when you register your account on an exchange, for example.

Generally speaking, you cannot have a transaction executed with one account and paid for with another account; the account executing the transaction will always be the one paying for it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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