Как можно вызвать оплачиваемую функцию в другом контракте с аргументами и отправить средства?

У меня есть контракт с именем 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
  }
}

Вот Mainконтракт:

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

Итак, я хочу, чтобы всякий раз, когда кто-то отправляет эфиры Callконтракту, он пересылал все эфиры Mainконтракту при выполнении callфункции в Mainконтракте с необходимыми аргументами.

Можно ли это сделать?

Ответы (2)

Обновление для комментария @Girish, в Solidity 0.6+ синтаксис изменился на:address.function{value:msg.value}(arg1, arg2, arg3)


Оригинал

Общий синтаксис для вызова функции в другом контракте с аргументами и отправки средств:address.func.value(amount)(arg1, arg2, arg3)

funcдолжен иметь payableмодификатор (для Solidity 0.4+).

Завершая ответ @Edmund этими важными деталями, вот пример, который компилируется:

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
  }
}

Также подчеркнув то, что он написал:

Имейте в виду, что это сработает только в том случае, если люди, отправляющие средства, отправят достаточно газа, чтобы покрыть вызов Main и все, что вы в нем делаете.

о вашем комментарии о msg.sender, значением msg.senderбудет адресPayMin
Начиная с Solidity 0.6.0, address.function.value(amount)(arg1, arg2, arg3) устарел. Вместо этого используйте address.function{value:msg.value}(arg1, arg2, arg3).
@GirishThimmegowda Спасибо, я добавил в начало ответа. (Сейчас нет времени, чтобы протестировать и обновить весь ответ.)

Да, это можно сделать. Однако не звоните call«позвонить» — это напрашивается на неприятности.

Вам понадобится контракт, который получает платеж, чтобы узнать адрес вашего основного контракта. Представьте, что он хранится в переменной с именем main_addr, а у Main есть метод handlePayment(), вы можете вызвать его примерно так:

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

Это также может принимать параметры, например, вы можете указать, что вы получили msg.senderи msg.value.

Имейте в виду, что это сработает только в том случае, если люди, отправляющие средства, отправят достаточно газа, чтобы покрыть вызов Main и все, что вы в нем делаете. В некоторых ситуациях может быть лучше просто зарегистрировать событие в оплачиваемом контракте и обработать его позже.

Не могли бы вы уточнить, как этот способ вызова может принимать дополнительные параметры?
См. ответ @eth.
не отвечает на вопрос