We need to call 2 methods of 2 different contracts in Ethereum, and this should be batched in one transaction, either both of them be confirmed or both of them be rejected.

Exactly We want user to pay some ERC20 tokens to a method of a contract X, so first he should call .appove() method of the token contract, then he should call a desired method in the contract X that it call .transferFrom method of the token contract.

Because of some requirements we need to pass some parameters to the method of contract X, it is not possible to send tokens directly to contract X.

If we use another contract Y for this purpose, the caller of .appove() method will not be the main msg.sender.

Is there any way to avoid calling these 2 separate transactions?

  • So you're calling the second contract from the first contract and the msg.sender is the address of the first contract instead of the main msg.sender (your address) , am i right? – Masoud jt Jun 26 at 17:59
  • 2
    Does this answer your question? How to call two functions in atomic transaction from web3 node client – Ismael Jun 26 at 19:02
  • @Masoudjt If we call .approve() method from the first contract, Itwill not be the right solution. We should call it from the client. – Alireza Zojaji Jun 26 at 20:21
  • @Ismael Not at all, this question is completely different. – Alireza Zojaji Jun 26 at 20:24
  • It's not very clear. I'm not sure. You want to call X, then Y with arguments from X, then X gets paid tokens (contract T) and you want all this in one move? Or, are you looking for an alternative to approve and then transferFrom? – Rob Hitchens Jul 1 at 7:19

This is a design issue with ERC-20 standard.

It has been not fixed until later ERC-777 standard and its send() method. Unfortunately, most of ERC-20 token contracts cannot be upgraded. You need to keep supporting this bad UX pattern forever.

More here: Gasless transaction and easy token Solidity receiver callbacks for ERC-20 tokens

Edit: Well there is a way but it is little bit different approach. For example Coinbase merchant services and centralised exchanges use this. You need to create a payment forwarded smart contracts (centrally) upfront and then assign the user to deposit to one of these forwarder smart contracts. transfer() is suppored. You cannot do this fully decentralised manner, you need a centralised coordinator.


| improve this answer | |
  • I want to use USDT token. It is not under my control. – Alireza Zojaji Jul 1 at 17:48
  • 1
    Then you need to deal with 2 transactions issue until there is USDT token 2.0. – Mikko Ohtamaa Jul 1 at 20:12
  • 1
    @AlirezaZojaji Please see the edit - could be applicable to your use case – Mikko Ohtamaa Jul 3 at 7:44

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.