В Solidity взаимодействие между контрактами осуществляется посредством вызовов. Ниже приведены некоторые основные методы вызова контракта:
Контракт может выполнять внутренние вызовы, вызывая свои собственные внутренние функции или частные функции. Этот метод вызова не создает новый контекст выполнения; вызываемая функция разделяет контекст выполнения функции, которая ее вызвала.
contract A {
function foo() internal {
// ...
}
function bar() public {
foo(); // внутренний звонок
}
}
внешний Вызов — наиболее распространенный способ вызова контракта. Контракт может выполняться внешне, вызывая общедоступную или внешнюю функцию другого контракта. вызов. Этот метод вызова создает новый контекст выполнения.,Вызванный контракт имеет свой собственныйthis
иmsg.sender
。
contract A {
function foo() external {
// ...
}
}
contract B {
A a = new A();
function bar() public {
a.foo(); // внешний вызов
}
}
Контракт может пройтиdelegatecall
илиstaticcall
вызвать другой контрактфункция。Этот метод вызова поддерживает контекст выполнения вызывающего объекта.,включатьthis
иmsg.sender
。Это означает, чтофункция Доступени Изменить статус звонящего。Этот метод вызова часто используется для реализации библиотек.функцияили Обновление контракта。
contract A {
function foo() external {
// ...
}
}
contract B {
function bar(address _a) public {
_a.delegatecall(abi.encodeWithSignature("foo()")); // Делегатский звонок
}
}
Контракт может пройтиcall
,delegatecall
,staticcall
илиcallcode
Подождите низкого уровняфункцияпозвонить。Этифункция Принимает параметр байтовой строки,Первые 4 байта этой строки представляют собой селектор функций.,Следующие байты являются функциональными параметрами. Этот метод вызова обеспечивает большую гибкость,Но и ошибаться легче.
contract A {
function foo() external {
// ...
}
}
contract B {
function bar(address _a) public {
_a.call(abi.encodeWithSignature("foo()")); // вызов низкого уровня
}
}
Чтобы повысить читаемость и безопасность кода, обычно определяется интерфейс для выполнения внешних вызовов.
interface ITarget {
function setX(uint _x) external;
}
contract ExternalCallWithInterface {
function callSetX(address _contract, uint _x) public {
ITarget(_contract).setX(_x);
}
}
При совершении внешних вызовов в Solidity следует учитывать несколько важных моментов:
1.Проверьте результат звонка:внешний Вызов может завершиться неудачно, например, вызываемый контракт не существует или вызывающая функция выдает исключение. Поэтому вам всегда следует проверять внешний вид. вызоввозвращаемое значение,и соответствующим образом справляться с ситуациями сбоев。2.Используйте газ с осторожностью:внешний вызов может потреблять много газа. Если вы выполняете внешний цикл вызов, который может привести к сбою транзакции из-за исчерпания газа. Поэтому вам следует стараться избегать выполнения внешнего кода в цикле. вызов,илииспользуетсяgasleft()
функциячтобы проверить оставшиесяgas。3.Предотвращение повторных атак:Если вы звоните внешнемуфункция Есть еще важная логика, которую нужно будет выполнить позже.,Может подвергаться повторным атакам. Злоумышленник может снова вызвать ваш контракт в вызываемой функции.,Таким образом, изменяется состояние контракта до того, как ваша логика будет завершена. Для предотвращения повторных атак,Вам следует позвонить внешнемуфункция Завершите все обновления статуса до。4.Используйте низкоуровневые функции с осторожностью.:call
,delegatecall
,staticcall
иcallcode
Подождите низкого уровняфункция Обеспечивает большую гибкость,Но и ошибаться легче.Например,Если вы неправильно закодируете селекторы функций и параметры,Может быть вызвана неправильная функция. поэтому,без необходимости,В противном случае вам следует стараться избегать использования низкоуровневогофункция。5.Обратите внимание на контроль разрешений:При вызове других контрактовфункциячас,Вам нужен контакт внимание на контроль разрешений。Например,Если вы вызываете публичную функцию другого контракта,Вам необходимо убедиться, что эта функция может быть вызвана вашим контрактом. Если вы вызываете частную или внутреннюю функцию другого контракта,Вам необходимо убедиться, что в вашем контракте есть разрешение на вызов этой функции.
Отказ от ответственности: эта работа распространяется под лицензией Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)[1]. Пожалуйста, укажите источник при ее использовании. Автор: мэнбин[2] блог: мэнбин[3] Гитхаб: mengbin92[4] cnblogs: Непреднамеренно полюбила воду[5] Сообщество разработчиков облачных технологий Tencent: Мюнстер[6]
[1]
С указанием авторства-Некоммерческая-ShareAlike 4.0 интернациональность (CC BY-NC-SA 4.0): https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh
[2]
mengbin: mengbin1992@outlook.com
[3]
mengbin: https://mengbin.top
[4]
mengbin92: https://mengbin92.github.io/
[5]
Влюбляюсь в воду нечаянно: https://www.cnblogs.com/lianshuiwuyi/
[6]
Мюнстер: https://cloud.tencent.com/developer/user/6649301