I have a contract with the following function:

function offerTokenTribute(address[] _tokenContractAddresses, uint256[] _tokenTributes) public {
  require(_tokenContractAddresses.length == _tokenTributes.length);

  Member storage member = members[msg.sender];
  member.approved = false; // should be already, but lets be safe

  for (uint8 i = 0; i < _tokenContractAddresses.length; i++) {
    ERC20 erc20 = ERC20(_tokenContractAddresses[i]);
    erc20.approve(this, _tokenTributes[i]);

  TokenTributeOffered(msg.sender, _tokenContractAddresses, _tokenTributes);

The problem is the erc20.approve function is not approving on behalf of the original msg.sender, it is changing msg.sender to the contract address (I verified this by checking allowances).

Is there any way to do this from my contract, or is the only solution to call the approval outside of my contract (non-ideal)?

1 Answer 1


No, there is no way around it.

It is a security feature, a contract cannot impersonate other account.

  • However, a well sound use case may require to run in a single transaction both: Alice approves (Bob,1000) AND Bob transfers from (Alice to Charlie, 1000) How this can be done?
    – Davide C
    Commented Sep 19, 2018 at 11:29
  • Allowing a contract to impersonate a user or another contract can be a security nightmare at the EVM level if not implemented correctly. It is more practical if it is implemented at the contract level, perhaps ERC 777 can be used for that functionality.
    – Ismael
    Commented Sep 19, 2018 at 15:16

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.