To execute the transfer or transferFrom ERC-20 token functions in a Solidity contract, ie:

// moves token from contract to personal address
        ERC20Token.transfer(msg.sender, tokenamount);
// moves token from personal account to contract 
        ERC20Token.transferFrom(msg.sender, address(this), tokenamount);

I must first execute the approve function in javascript outside solidity, like this:

  contract = w3.eth.contract(address=contract_address, abi=contract_abi['abi'])
  nonce = w3.eth.getTransactionCount(wallet_address)
  txn_dict = contract.functions.approve(contract_address, amount).buildTransaction({
  'gas': 500000,
  'gasPrice': w3.toWei(gas_p, 'gwei'),
  'nonce': nonce,
signed_txn = w3.eth.account.signTransaction(txn_dict, private_key=wallet_private_key)
result = w3.eth.sendRawTransaction(signed_txn.rawTransaction)

I was wondering if it was possible to put that 'approve' method into the Solidity contract, but then thought, this would be bad because a malicious contract might execute the approve & transfer functions within the same block, allowing a token overspend. Is that the right way to think about it? [I could be wrong in my assumption that you cannot approve an ERC-20 token expenditure within a Solidity contract]

It's interesting because, on one hand, I could imagine the token's allowance amount would be modified when a transfer function was called, or not, depending on whether the Solidity contracts are run sequentially in a block, or simultaneously.

1 Answer 1


It's not possible to call approve from a Solidity contract on behalf of a user. You can use it to allow another contract to spend the tokens in the contract itself. The approve function looks like this:

function approve(address _spender, uint256 _value) public returns (bool success)

As you can see, there is no way to specify the address to approve for. It will use msg.sender, which in the case of calling it from a contract, would be the address of the contract itself. That means the user has to send a transaction from their own address in order to allow _spender (which could be a contract) to send the tokens.

  • Thanks. Can you address whether or not my inference about why this function is restricted this way is correct? Specifically, that if 'approve' was accessible within a contract, one could then transfer more than the approved amount in a single contract's execution? Sep 1, 2020 at 15:27
  • I think what you are referring to is a reentrancy attack. Token contracts themselves should have some kind of protection from these attacks. I think the reason why a smart contract cannot call approve on behalf of the user is authorisation: the token contract cannot (with the current specification) verify that the user wants to approve. There are some other token standards like ERC-777 that use a different approach for allowance, so that the user won't have to send two transactions.
    – Morten
    Sep 1, 2020 at 15:45

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.