38

I have a contract named Call:

contract Call {
  ...
  function () payable {
    // TODO: Call the call function in the main contract
    // and forward all funds (msg.value) sent to this contract
    // and passing in the following data: msg.sender
  }
}

Here is the Main contract:

contract Main {
  ...
  function call(address senderAddress) public {
    // Make the code in here run when someone sends ethers to the Call contract
  }
}

So, I want to have it so that whenever someone sends ethers the Call contract, it forwards all the ethers to the Main contract while running the call function in the Main contract with the necessary arguments.

Can this be done?

2 Answers 2

59

Update per @Girish comment, in Solidity 0.6+ the syntax has changed to: address.function{value:msg.value}(arg1, arg2, arg3)


Original

The general syntax for calling a function in another contract with arguments and sending funds is: address.func.value(amount)(arg1, arg2, arg3)

func needs to have the payable modifier (for Solidity 0.4+).

Completing @Edmund's answer with these important details, here's an example that compiles:

pragma solidity ^0.4.0;

contract PayMain {
  Main main;
  function PayMain(address _m) {
     main = Main(_m);
  }
  function () payable {
    // Call the handlePayment function in the main contract
    // and forward all funds (msg.value) sent to this contract
    // and passing in the following data: msg.sender
    main.handlePayment.value(msg.value)(msg.sender);
  }
}

contract Main {
  function handlePayment(address senderAddress) payable public {
      // senderAddress in this example could be removed since msg.sender can be used directly
  }
}

Also emphasizing what he wrote:

Be aware that this will only work if the people sending the funds send enough gas to cover the call to Main and whatever you do in it.

2
  • 1
    about your comment about msg.sender, the value of msg.sender will be the address of PayMin
    – Victory
    Apr 3, 2018 at 23:13
  • 6
    As of Solidity 0.6.0, address.function.value(amount)(arg1, arg2, arg3) is deprecated. Use address.function{value:msg.value}(arg1, arg2, arg3) instead. May 24, 2020 at 18:42
3

Yes, this can be done. Don't call call "call" though - it's asking for trouble.

You'll need the contract that receives the payment to know the address of your Main contract. Imagining it's stored in a variable called main_addr, and Main has a method called handlePayment(), you can call it with something like:

Main m = Main(main_addr);
m.handlePayment();

This can also take parameters, eg you may want to tell it what you got in msg.sender and msg.value.

Be aware that this will only work if the people sending the funds send enough gas to cover the call to Main and whatever you do in it. In some situations it may be better to just log an event in the payable contract and handle it later.

3
  • Could you please be more specific on how can this way of calling take further parameters?
    – comodoro
    Jan 18, 2017 at 20:44
  • See @eth's answer. Jan 18, 2017 at 23:34
  • doesn't answer the question
    – ihor.eth
    May 12, 2022 at 22:46

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.