Нещодавно я заново вивчав solidity, консолідував деталі та писав “Solidity Minimalist Primer” для початківців (хлопці з програмування можуть знайти інший підручник), який оновлюється 1-3 рази на тиждень.
Весь код та навчальні посібники мають відкритий вихідний код на GitHub: github.com/AmazingAng/WTFSolidity
У лекції 17: Надсилання ETH, ми говорили про використання call для надсилання ETH, і в цій лекції ми покажемо вам, як використовувати його для виклику контрактів.
Дзвінок
call – це низькорівнева функція-член типу address, яка використовується для взаємодії з іншими контрактами. Він повертає (булеве значення, дані), що відповідає успішності виклику та значенню, що повертається цільової функції відповідно.
call є офіційно рекомендованим способом надсилання ETH шляхом запуску резервних функцій або функцій отримання за допомогою solidity. Не рекомендується дзвонити в інший договір дзвінком, тому що коли ви викликаєте функцію небезпечного контракту, ви віддаєте йому ініціативу. Рекомендованим методом, як і раніше, є виклик функції після оголошення змінної контракту, дивись Лекція 19: Виклик інших контрактів. Якщо ми не знаємо вихідного коду або ABI контракту іншої сторони, ми не можемо генерувати змінні контракту, але ми все одно можемо викликати функції контракту іншої сторони через виклик.
Правила використання call
Правила використання call наступні:
Двійкове кодування використовує структуровану функцію кодування abi.encodeWithSignature для отримання:
Сигнатурою функції є «Назва функції (тип параметра, розділений комами)». Наприклад, abi.encodeWithSignature(“f(uint256,address)”, _x, _addr).
Крім того, при виклику контракту можна вказати кількість ETH і газу, які будуть відправлені транзакцією:
Це здається трохи складним, тому давайте розглянемо приклад програми для дзвінків.
Цільовий контракт
Почнемо з написання простого цільового контракту, OtherContract, і розгортання його, код в основному такий же, як і в Лекції 19, за винятком додавання резервної функції.
Цей контракт містить змінну стану x, журнал подій, який спрацьовує при отриманні ETH, і три функції:
getBalance(): повертає ETH баланс контракту. setX(): зовнішня функція до оплати, яка може встановити значення x і відправити ETH на контракт. getX(): зчитує значення x.
Використовуйте call для виклику цільового контракту
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. Виклик все ще може бути успішно виконаний і повернути успішний, але насправді він є резервною функцією цільового контракту, що викликається.
Підсумки
У цій доповіді ми показали, як використовувати низькорівневий виклик функції для виклику інших контрактів. Call не є рекомендованим методом виклику контракту, оскільки він не є безпечним. Але корисно дозволити нам викликати цільовий контракт, не знаючи вихідного коду та ABI.
Переглянути оригінал
Ця сторінка може містити контент третіх осіб, який надається виключно в інформаційних цілях (не в якості запевнень/гарантій) і не повинен розглядатися як схвалення його поглядів компанією Gate, а також як фінансова або професійна консультація. Див. Застереження для отримання детальної інформації.
Початок роботи з Solidity|Лекція 22: Дзвінок
Нещодавно я заново вивчав solidity, консолідував деталі та писав “Solidity Minimalist Primer” для початківців (хлопці з програмування можуть знайти інший підручник), який оновлюється 1-3 рази на тиждень.
Весь код та навчальні посібники мають відкритий вихідний код на GitHub: github.com/AmazingAng/WTFSolidity
У лекції 17: Надсилання ETH, ми говорили про використання call для надсилання ETH, і в цій лекції ми покажемо вам, як використовувати його для виклику контрактів.
Дзвінок
call – це низькорівнева функція-член типу address, яка використовується для взаємодії з іншими контрактами. Він повертає (булеве значення, дані), що відповідає успішності виклику та значенню, що повертається цільової функції відповідно.
call є офіційно рекомендованим способом надсилання ETH шляхом запуску резервних функцій або функцій отримання за допомогою solidity. Не рекомендується дзвонити в інший договір дзвінком, тому що коли ви викликаєте функцію небезпечного контракту, ви віддаєте йому ініціативу. Рекомендованим методом, як і раніше, є виклик функції після оголошення змінної контракту, дивись Лекція 19: Виклик інших контрактів. Якщо ми не знаємо вихідного коду або ABI контракту іншої сторони, ми не можемо генерувати змінні контракту, але ми все одно можемо викликати функції контракту іншої сторони через виклик.
Правила використання call
Правила використання call наступні:
Двійкове кодування використовує структуровану функцію кодування abi.encodeWithSignature для отримання:
Сигнатурою функції є «Назва функції (тип параметра, розділений комами)». Наприклад, abi.encodeWithSignature(“f(uint256,address)”, _x, _addr).
Крім того, при виклику контракту можна вказати кількість ETH і газу, які будуть відправлені транзакцією:
Це здається трохи складним, тому давайте розглянемо приклад програми для дзвінків.
Цільовий контракт
Почнемо з написання простого цільового контракту, OtherContract, і розгортання його, код в основному такий же, як і в Лекції 19, за винятком додавання резервної функції.
Цей контракт містить змінну стану x, журнал подій, який спрацьовує при отриманні ETH, і три функції:
getBalance(): повертає ETH баланс контракту. setX(): зовнішня функція до оплати, яка може встановити значення x і відправити ETH на контракт. getX(): зчитує значення x.
Використовуйте call для виклику цільового контракту
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. Виклик все ще може бути успішно виконаний і повернути успішний, але насправді він є резервною функцією цільового контракту, що викликається.
Підсумки
У цій доповіді ми показали, як використовувати низькорівневий виклик функції для виклику інших контрактів. Call не є рекомендованим методом виклику контракту, оскільки він не є безпечним. Але корисно дозволити нам викликати цільовий контракт, не знаючи вихідного коду та ABI.