Как вызвать функцию из уже развернутого контракта?

Я попытался использовать функцию «Вызов», как описано здесь: Функция вызова из развернутого контракта

Но кажется, что он вообще не работает.

Как я могу вызвать функцию из существующего развернутого смарт-контракта?

Я пытаюсь вызвать простую функцию из существующего адреса, которая получает адрес в качестве параметра.

Это код, который я использую для вызова внешней функции:

Контракт А:

function CallExternalFunction(address externalContractAddress) 
{    
    externalContractAddress.call(bytes4(sha3("FunctionX(address)")),0xfffff);
    //sends 0xfffff as input parameter to the external contract
}

Исходный код уже развернутого контракта выглядит так:

Контракт Б:

contract test { 

mapping (address => uint256) public balanceOf; 

function test() { 

}

function FunctionX(address _address)
{
    balanceOf[_address] = 50000;    
}
}
У вас есть исходный код или ABI контракта для вызова?
Я обновил вопрос с исходным кодом
Кажется, что в этом подходе нет ничего плохого; это просто вызов внешнего контракта более низкого уровня. Есть только несколько предостережений. Весь callваш газ (минус ~ 30 тыс.) будет перенаправлен внешнему контракту, чтобы делать с ним все, что ему заблагорассудится, что является уязвимостью, особенно если вызов завершается сбоем и по умолчанию используется резервная функция. callтакже нарушает безопасность типов для аргументов функции и по-прежнему будет передавать эфир, если при выполнении генерируется исключение, поэтому обязательно поместите вызов в a require(), чтобы отменить транзакции, которые ведут себя не так, как ожидалось.

Ответы (1)

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

contract Caller {

  test public t;

  function Caller() {
    t = new test();
  }

  function callIt(address theAddress)
    public
    returns(bool success)
  {
    t = test(t); <===== here the other contract address can be called t = test([OtherContractAddress]); example: test(0x12345);
    bool result = t.FunctionX(theAddress);
    return result;
  }
}

contract test { 

  mapping (address => uint256) public balanceOf; 

  function FunctionX(address _address) public returns(bool success)
  {
    balanceOf[_address] = 50000; 
    return true;
  }
}

В Remix, чтобы показать, что это работает.

введите описание изображения здесь

Вы можете использовать аналогичную структуру для контракта, который уже есть, если у вас есть исходный код, используя и интерфейсный контракт. Здесь компилятор «вызывающий» может видеть достаточно теста {} для управления интерфейсом.

contract Caller {

  test public t;

  // where test is deployed and the address is known
  // Pass in the address for test {}.

  function Caller(address tAddress) {
    t = test(tAddress); // address of contract t
  }

  function callIt(address theAddress)
    public
    returns(uint bal)
  {
      return t.FunctionX(theAddress);
  }
}

// This interface constant includes the function interfaces (exactly as in the "real" contract" with the fynctions undefined
// This tells the compiler how to communicate with the ABI in test{}.

contract test { 
  function FunctionX(address _address) public returns(uint balanceOf) {}
}
Показанный вами пример кажется двумя контрактами с одним и тем же развернутым адресом, верно? В моем случае контракты A и B развернуты по разным адресам (я обновил описание контрактами A и B). Знаете ли вы, как заставить его работать, когда контракты развернуты по разным адресам?
Нет. Два контракта по одному адресу невозможны. Два контракта в одном исходном файле, причем первый контракт развертывает экземпляр другого (один из способов узнать адрес другого). Звонящий по адресу 0xb872, тестовый по адресу 0x22e6. t = new test();развертывает новый экземпляр test. Для уже развернутого test{} вы можете передать адрес или жестко закодировать адрес. Вызывающий должен знать его, чтобы позвонить. Единственный исходный файл дает компилятору представление о тестовом контракте, поэтому он понимает интерфейс test{} и имеет байт-код, необходимый для развертывания нового теста{}.
Мне нравится идея с предварительным объявлением. Обратите внимание, что компилятор (solcjs) генерирует предупреждение «Неиспользуемая локальная переменная» для _address в приведенном выше примере.