Синхронный вызов функции внешнего контракта в Solidity

У меня есть два контракта Solidity, где контракт Callerзависит от второго контракта Callee. Контракт Calleeпредоставляет функцию публичного просмотра, которая проверяет правильность строки (например, пароля) в соответствии с некоторыми внутренними правилами. Callerдолжен проверить строку в своей собственной функции, вызвав Callee, прежде чем он сможет продолжить обработку. Кроме того, Callerнеобходимо вызвать функцию с Calleeпомощью delegatecall, потому что внутренняя проверка правильности учитывает адрес вызывающего абонента.

contract Caller {

  function doSomething(string _text, address _callee) public {
     bool valid = bool(_callee.delegatecall(
                          bytes4(keccak256("check(string _text)")), _text)
                  );

     require(valid == true);
     /* further process if text is valid */
  }
}

contract Callee {

  function check(string _text) public view returns(bool){
    /* validity check */
    return true;
  }
}

Проблема с этим кодом в том, что вызов функции checkкажется асинхронным, и поэтому requireоператор в функции doSomethingвсегда будет терпеть неудачу. Это проблема delegatecall? Есть ли способ синхронно вызвать внешнюю функцию?

Ответы (1)

Наконец-то я нашел ответ на свою проблему: к сожалению, нельзя получить значения из вызовов функции delegatecall.

Что ж, виртуальная машина ДЕЙСТВИТЕЛЬНО поддерживает возвращаемые значения в DELEGATECALLкоде операции:func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error)
Действительно? Правильно ли я прочитал код операции: он может возвращать массив байтов?
Я не очень хорошо разбираюсь в написании контрактов, но опкод DELGATECALL работает так же, как опкод CALL. Я знаю, потому что я модифицировал виртуальную машину для пользовательской обработки блокчейна. Он абсолютно идентичен, откройте core/vm/instructions.go и убедитесь сами. Переменная retсодержит []byteмассив, возвращенный DELEGATECALL. Возможно, вы можете написать небольшую часть своего контракта на ассемблере, поэтому вы вызываете DELEGATECALL и перехватываете это возвращаемое значение. Это возвращаемое значение помещается в память в outOffsetпозицию.
Я думаю, что эта retпеременная указывает, была ли обработка вызванной функции успешной.
нет, retэто вывод, возвращаемый EVM. Если произошла какая-либо ошибка, он возвращает файл error. Этот вывод кодируется в соответствии с ABI. Если вы вызовете abi.Unpack(), retвы получите значение в соответствии с его типом. Например, все целые числа хранятся в массивах по 32 байта, все строки имеют первую длину строки, затем следуют строковые данные и так далее...