Начало работы с Solidity|Лекция 22: Звонок

律动

Недавно я заново изучал solidity, консолидировал детали и писал “Solidity Minimalist Primer” для начинающих (программисты могут найти другое руководство), обновляемое 1-3 раза в неделю.

Весь код и учебные пособия находятся с открытым исходным кодом на GitHub: github.com/AmazingAng/WTFSolidity

В Лекции 17: Отправка ETH мы говорили об использовании call для отправки ETH, и в этой лекции мы покажем вам, как использовать его для вызова контрактов.

Вызов

call — это низкоуровневая функция-член типа адрес, которая используется для взаимодействия с другими контрактами. Возвращает (bool, data), что соответствует успешному выполнению вызова и возвращаемому значению целевой функции соответственно.

call является официально рекомендуемым методом отправки ETH путем запуска функций fallback или receive по solidity. Не рекомендуется вызывать другой контракт с вызовом, потому что, вызывая функцию небезопасного контракта, вы отдаете ей инициативу. Рекомендуемым методом по-прежнему является вызов функции после объявления переменной контракта, см. Лекция 19: Вызов других контрактов. Если мы не знаем исходный код или ABI контракта другой стороны, мы не можем генерировать переменные контракта, но мы все равно можем вызывать функции контракта другой стороны через call.

Правила использования call

Правила использования call следующие:

Двоичная кодировка использует функцию структурированного кодирования abi.encodeWithSignature для получения:

Сигнатура функции: “Имя функции (тип параметра, разделенного запятыми)”. Например, abi.encodeWithSignature(“f(uint256,address)”, _x, _addr).

Кроме того, при вызове контракта можно указать количество ETH и газа, которое будет отправлено транзакцией:

Это кажется немного сложным, поэтому давайте возьмем пример приложения для звонков.

Целевой контракт

Давайте начнем с написания простого целевого контракта OtherContract и его развертывания, код в основном такой же, как и в Лекции 19, за исключением добавления резервной функции.

Этот контракт содержит переменную состояния x, журнал событий, который запускается при получении ETH, и три функции:

getBalance(): Возвращает баланс ETH контракта. setX(): внешняя оплачиваемая функция, которая может установить значение x и отправить ETH на контракт. getX(): Считывает значение x.

Использовать вызов для вызова целевого контракта

1. Ответное событие

Давайте напишем контракт Call для вызова целевой функции контракта. Прежде всего, напишем определение события Response и выведем успешное выполнение и данные, возвращенные вызовом, чтобы мы могли наблюдать возвращаемое значение.

2. Вызов функции setX

Мы определяем функцию callSetX для вызова setX() целевого контракта, переносим количество ETH в msg.value и выпускаем событие Response для вывода успеха и данных:

Затем мы вызываем callSetX, чтобы изменить переменную состояния _x на 5, а параметрами являются адрес OtherContract и 5, потому что целевая функция setX() не возвращает значение, поэтому выходные данные события Response равны 0x, то есть пусты.

3. Вызов функции getX

Вызовем функцию getX(), которая вернет значение целевого контракта _x типа uint256. Мы можем использовать abi.decode для декодирования возвращаемого значения вызова, данных и считывания значения.

Из выходных данных события Response мы видим, что данные 0x0000000000000000000000000000000000000000000000000000000000000005. После abi.decode окончательное возвращаемое значение равно 5.

4. Вызов функции, которая не существует

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

В приведенном выше примере мы вызвали несуществующую функцию foo. Вызов по-прежнему может быть успешно выполнен и вернуть success, но на самом деле это резервная функция вызываемого целевого контракта.

Резюме

В этом докладе мы показали, как использовать вызов низкоуровневой функции для вызова других контрактов. call не является рекомендуемым методом вызова контракта, так как он небезопасен. Но полезно позволить нам вызывать целевой контракт, не зная исходного кода и ABI.

Отказ от ответственности: Информация на этой странице может поступать от третьих лиц и не отражает взгляды или мнения Gate. Содержание, представленное на этой странице, предназначено исключительно для справки и не является финансовой, инвестиционной или юридической консультацией. Gate не гарантирует точность или полноту информации и не несет ответственности за любые убытки, возникшие от использования этой информации. Инвестиции в виртуальные активы несут высокие риски и подвержены значительной ценовой волатильности. Вы можете потерять весь инвестированный капитал. Пожалуйста, полностью понимайте соответствующие риски и принимайте разумные решения, исходя из собственного финансового положения и толерантности к риску. Для получения подробностей, пожалуйста, обратитесь к Отказу от ответственности.
комментарий
0/400
Нет комментариев